Compare commits
No commits in common. "master" and "v1.2.3" have entirely different histories.
3
.github/ISSUE_TEMPLATE.md
vendored
|
@ -21,4 +21,7 @@
|
||||||
Description:
|
Description:
|
||||||
What this is about, what happens and what is expected to happen. What needs to be done for it to happen.
|
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.
|
If a crash is happening a log is needed. Screenshots or demonstration videos are always helpful too.
|
||||||
|
|
||||||
|
About logging:
|
||||||
|
https://gsantner.net/android-contribution-guide/?packageid=com.github.dfa.diaspora_android&name=dandelion&web=https://github.com/gsantner/dandelion#logcat
|
||||||
-->
|
-->
|
||||||
|
|
68
.github/workflows/build-android-project.yml
vendored
|
@ -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
|
|
1
.gitignore
vendored
|
@ -36,7 +36,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)
|
||||||
|
|
48
.travis.yml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
language: android
|
||||||
|
jdk: oraclejdk8
|
||||||
|
|
||||||
|
before_cache:
|
||||||
|
# Do not cache a few Gradle files/directories (see https://docs.travis-ci.com/user/languages/java/#Caching)
|
||||||
|
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||||
|
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
# Android SDK
|
||||||
|
- $HOME/android-sdk-dl
|
||||||
|
- $HOME/android-sdk
|
||||||
|
|
||||||
|
# Gradle dependencies
|
||||||
|
- $HOME/.gradle/caches/
|
||||||
|
- $HOME/.gradle/wrapper/
|
||||||
|
|
||||||
|
# Android build cache (see http://tools.android.com/tech-docs/build-cache)
|
||||||
|
- $HOME/.android/build-cache
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Download and unzip the Android SDK tools (if not already there thanks to the cache mechanism)
|
||||||
|
# Latest version available here: https://developer.android.com/studio/index.html#downloads
|
||||||
|
- if test ! -e $HOME/android-sdk-dl/sdk-tools.zip ; then curl https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip > $HOME/android-sdk-dl/sdk-tools.zip ; fi
|
||||||
|
- unzip -qq -n $HOME/android-sdk-dl/sdk-tools.zip -d $HOME/android-sdk
|
||||||
|
|
||||||
|
# Install or update Android SDK components (will not do anything if already up to date thanks to the cache mechanism)
|
||||||
|
- echo y | $HOME/android-sdk/tools/bin/sdkmanager 'tools' > /dev/null
|
||||||
|
- echo y | $HOME/android-sdk/tools/bin/sdkmanager 'platform-tools' > /dev/null
|
||||||
|
- echo y | $HOME/android-sdk/tools/bin/sdkmanager 'build-tools;26.0.2' > /dev/null
|
||||||
|
- echo y | $HOME/android-sdk/tools/bin/sdkmanager 'platforms;android-27' > /dev/null
|
||||||
|
- echo y | $HOME/android-sdk/tools/bin/sdkmanager 'extras;google;m2repository' > /dev/null
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- gh-pages
|
||||||
|
- l10n_master
|
||||||
|
- crowdin
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- ANDROID_HOME=$HOME/android-sdk
|
||||||
|
matrix:
|
||||||
|
- TASK="clean lintFlavorDefaultDebug --stacktrace"
|
||||||
|
- TASK="clean build check -x lint --stacktrace"
|
||||||
|
|
||||||
|
script: "./gradlew --no-daemon --parallel $TASK"
|
14
CHANGELOG.md
|
@ -1,16 +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
|
### v1.2.3
|
||||||
**Improved:**
|
**Improved:**
|
||||||
- More supported languages, more complete translations!
|
- More supported languages, more complete translations!
|
||||||
|
@ -23,6 +10,7 @@
|
||||||
|
|
||||||
**New features:**
|
**New features:**
|
||||||
- All new Aspects and Tags, using a searchable dialog
|
- All new Aspects and Tags, using a searchable dialog
|
||||||
|
- A new home - project blog/page: <https://gsantner.net/project/dandelion.html>
|
||||||
|
|
||||||
**Fixed:**
|
**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.
|
- 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.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<!--
|
<!--
|
||||||
This file contains references to people who contributed to the app.
|
This file contains references to people who contributed to the app.
|
||||||
|
You can also send a mail to [gsantner AT mailbox DOT org](http://gsantner.net#contact) to get included.
|
||||||
|
|
||||||
Schema: **[Name](Reference)**<br/>~° Text
|
Schema: **[Name](Reference)**<br/>~° Text
|
||||||
|
|
||||||
|
@ -8,11 +9,11 @@ Where:
|
||||||
* Reference: E-Mail, Webpage
|
* Reference: E-Mail, Webpage
|
||||||
* Text: Information about / kind of contribution
|
* Text: Information about / kind of contribution
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## LIST OF CONTRIBUTORS
|
## LIST OF CONTRIBUTORS
|
||||||
-->
|
-->
|
||||||
* **[Gregor Santner](http://github.com/gsantner)**<br/>~° Development of dandelion
|
* **[Gregor Santner](http://gsantner.net)**<br/>~° Current developer of dandelion
|
||||||
* **[Paul Schaub](https://github.com/vanitasvitae)**<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
|
* **[Martín Vukovic](martinvukovic AT protonmail DOT com)**<br/>~° Diaspora Native WebApp
|
||||||
* **[Gaukler Faun](https://github.com/scoute-dich)**<br/>~° Diaspora Native WebApp additions
|
* **[Gaukler Faun](https://github.com/scoute-dich)**<br/>~° Diaspora Native WebApp additions
|
||||||
|
@ -29,4 +30,3 @@ Where:
|
||||||
* **[Jean Lucas](jean AT 4ray DOT co)**<br/>~° Spanish translation
|
* **[Jean Lucas](jean AT 4ray DOT co)**<br/>~° Spanish translation
|
||||||
* **[asereze](https://github.com/asereze)**<br/>~° Sardinian translation
|
* **[asereze](https://github.com/asereze)**<br/>~° Sardinian translation
|
||||||
* **[Xosé M. Lamas](http://xmgz.eu)**<br />~° Galician translation
|
* **[Xosé M. Lamas](http://xmgz.eu)**<br />~° Galician translation
|
||||||
* **[massimiliano](https://framagit.org/massimiliano)**<br />~° Contributor
|
|
||||||
|
|
99
Makefile
|
@ -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
|
@ -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
|
|
41
README.md
|
@ -1,9 +1,9 @@
|
||||||
[![GitHub releases](https://img.shields.io/github/tag/gsantner/dandelion.svg)](https://github.com/gsantner/dandelion/releases)
|
[![GitHub release](https://img.shields.io/github/tag/gsantner/dandelion.svg)](https://github.com/gsantner/dandelion/releases)
|
||||||
[![GitHub downloads](https://img.shields.io/github/downloads/gsantner/dandelion/total.svg?logo=github&logoColor=lime)](https://github.com/gsantner/dandelion/releases)
|
[![Build Status](https://travis-ci.org/gsantner/dandelion.svg?branch=master)](https://travis-ci.org/gsantner/dandelion)
|
||||||
[![Translate on Crowdin](https://img.shields.io/badge/translate-crowdin-green.svg)](https://crowdin.com/project/diaspora-for-android/invite)
|
[![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&mail=gro.xobliam@@rentnasg)
|
||||||
[![Chat on Matrix](https://img.shields.io/badge/chat-matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org)
|
[![Chat - Matrix](https://img.shields.io/badge/chat-on%20matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org) [![Chat - FreeNode IRC](https://img.shields.io/badge/chat-on%20irc-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/?nick=dandelion-anon|?##dandelion)
|
||||||
[![GitHub CI](https://github.com/gsantner/dandelion/workflows/CI/badge.svg)](https://github.com/gsantner/dandelion/actions)
|
[![Donate](https://img.shields.io/badge/donate-appreciation-orange.svg)](https://gsantner.net/supportme/?project=dandelion&source=readme)
|
||||||
[![Codacy code quality](https://img.shields.io/codacy/grade/aff869c440bc48b7bd64680e97cbc453)](https://www.codacy.com/app/gsantner/dandelion)
|
[![Donate LiberaPay](https://img.shields.io/badge/donate-liberapay-orange.svg)](https://liberapay.com/gsantner/donate)
|
||||||
|
|
||||||
# dandelion\*
|
# dandelion\*
|
||||||
<img src="/app/src/main/ic_launcher-web.png" align="left" width="100" hspace="10" vspace="10">
|
<img src="/app/src/main/ic_launcher-web.png" align="left" width="100" hspace="10" vspace="10">
|
||||||
|
@ -39,11 +39,12 @@ dandelion\* requires access to the Internet and to external storage to be able t
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
The project is always open for contributions and accepts pull requests.
|
The project is always open for contributions and accepts pull requests.
|
||||||
The project uses [AOSP Java Code Style](https://source.android.com/source/code-style#follow-field-naming-conventions), with one exception: private members are `_camelCase` instead of `mBigCamel`. You may use Android Studios _auto reformat feature_ before sending a PR.
|
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. See [gsantner's android contribution guide](https://gsantner.net/android-contribution-guide/?packageid=com.github.dfa.diaspora_android&name=dandelion&web=https://github.com/gsantner/dandelion&source=readme#logcat) for more information.
|
||||||
|
|
||||||
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.
|
Translations can be contributed on GitHub or via [E-Mail](https://gsantner.net/#contact). 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 IRC or Matrix channel (bridged) 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) [![Chat - FreeNode IRC](https://img.shields.io/badge/chat-on%20irc-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/?nick=dandelion-anon|?##dandelion)
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,21 +62,23 @@ For more licensing informations, see [`3rd party licenses`](/app/src/main/res/ra
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
<div style="display:flex;" >
|
<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/diaspora-for-android/dandelion-metadata-latest/master/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/diaspora-for-android/dandelion-metadata-latest/master/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/diaspora-for-android/dandelion-metadata-latest/master/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/diaspora-for-android/dandelion-metadata-latest/master/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;" >
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/05.png" width="19%" style="margin-left:10px;" >
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:flex;" >
|
<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/diaspora-for-android/dandelion-metadata-latest/master/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/diaspora-for-android/dandelion-metadata-latest/master/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/diaspora-for-android/dandelion-metadata-latest/master/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;" >
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/09.png" width="19%" style="margin-left:10px;" >
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Notice
|
### Notice
|
||||||
#### Maintainers
|
#### Maintainers
|
||||||
- gsantner ([GitHub](https://github.com/gsantner), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c))
|
- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.net/supportme/?project=dandelion&source=readme), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c))
|
||||||
|
- Bitcoin: [1B9ZyYdQoY9BxMe9dRUEKaZbJWsbQqfXU5](https://gsantner.net/supportme/?project=dandelion&source=readme)
|
||||||
- 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
|
||||||
|
|
16
SCREENSHOTS.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
<div style="display:flex;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/01.png" width="19%" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/02.png" width="19%" style="margin-left:10px;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/03.png" width="19%" style="margin-left:10px;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/04.png" width="19%" style="margin-left:10px;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/05.png" width="19%" style="margin-left:10px;" >
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display:flex;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/06.png" width="19%" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/07.png" width="19%" style="margin-left:10px;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/08.png" width="19%" style="margin-left:10px;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/diaspora-for-android/dandelion-metadata-latest/master/en-US/phoneScreenshots/09.png" width="19%" style="margin-left:10px;" >
|
||||||
|
</div>
|
|
@ -6,27 +6,44 @@ if (enable_plugin_kotlin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
buildToolsVersion rootProject.ext.version_buildTools
|
compileSdkVersion version_setup_compileSdk
|
||||||
compileSdkVersion rootProject.ext.version_compileSdk
|
flavorDimensions "default"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android"
|
minSdkVersion version_setup_minSdk
|
||||||
applicationId "com.github.dfa.diaspora_android"
|
targetSdkVersion version_setup_targetSdk
|
||||||
versionName "1.3.5"
|
|
||||||
versionCode 46
|
|
||||||
vectorDrawables.useSupportLibrary = true
|
|
||||||
|
|
||||||
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[]", "DETECTED_ANDROID_LOCALES", "${findUsedAndroidLocales()}"
|
||||||
buildConfigField "String", "BUILD_DATE", "\"${getBuildDate()}\""
|
|
||||||
buildConfigField "String", "GITHASH", "\"${getGitHash()}\""
|
buildConfigField "String", "GITHASH", "\"${getGitHash()}\""
|
||||||
setProperty("archivesBaseName", applicationId + "-v" + versionCode + "-" + versionName)
|
resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android"
|
||||||
|
|
||||||
|
applicationId "com.github.dfa.diaspora_android"
|
||||||
|
versionName "1.2.3"
|
||||||
|
versionCode 36
|
||||||
|
|
||||||
|
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
if (enable_plugin_kotlin) {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions "default"
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
flavorDefault {
|
flavorDefault {
|
||||||
}
|
}
|
||||||
|
@ -40,58 +57,15 @@ android {
|
||||||
applicationId "net.gsantner.dandelior"
|
applicationId "net.gsantner.dandelior"
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorAtest {
|
flavorTest {
|
||||||
applicationId "net.gsantner.secondlion"
|
applicationId "net.gsantner.secondlion"
|
||||||
versionCode = Integer.parseInt(new Date().format('yyMMdd'))
|
versionCode = Integer.parseInt(new Date().format('yyMMdd'))
|
||||||
versionName = new Date().format('yyMMdd')
|
versionName = new Date().format('yyMMdd')
|
||||||
buildConfigField "boolean", "IS_TEST_BUILD", "true"
|
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 {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.all {
|
|
||||||
resolutionStrategy {
|
|
||||||
eachDependency { details ->
|
|
||||||
if (details.requested.group == 'com.android.support') {
|
|
||||||
if (details.requested.name != 'multidex' && details.requested.name != 'multidex-instrumentation') {
|
|
||||||
details.useVersion "${rootProject.ext.version_library_appcompat}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
packagingOptions {
|
|
||||||
exclude 'META-INF/LICENSE-LGPL-2.1.txt'
|
|
||||||
exclude 'META-INF/LICENSE-LGPL-3.txt'
|
|
||||||
exclude 'META-INF/LICENSE-W3C-TEST'
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
encoding = 'UTF-8'
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
disable 'MissingTranslation', 'InvalidPackage', 'ObsoleteLintCustomCheck', 'DefaultLocale', 'UnusedAttribute', 'VectorRaster', 'InflateParams', 'IconLocation', 'UnusedResources', 'TypographyEllipsis'
|
disable 'MissingTranslation'
|
||||||
abortOnError false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +75,7 @@ dependencies {
|
||||||
|
|
||||||
// Jars
|
// Jars
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.12'
|
||||||
|
|
||||||
// Android standard libs
|
// Android standard libs
|
||||||
implementation "com.android.support:appcompat-v7:${version_library_appcompat}"
|
implementation "com.android.support:appcompat-v7:${version_library_appcompat}"
|
||||||
|
@ -109,19 +83,16 @@ dependencies {
|
||||||
implementation "com.android.support:support-v4:${version_library_appcompat}"
|
implementation "com.android.support:support-v4:${version_library_appcompat}"
|
||||||
implementation "com.android.support:customtabs:${version_library_appcompat}"
|
implementation "com.android.support:customtabs:${version_library_appcompat}"
|
||||||
implementation "com.android.support:cardview-v7:${version_library_appcompat}"
|
implementation "com.android.support:cardview-v7:${version_library_appcompat}"
|
||||||
implementation "com.android.support:preference-v7:${version_library_appcompat}"
|
|
||||||
|
|
||||||
// UI libraries
|
// UI libraries
|
||||||
implementation "com.github.DASAR:ShiftColorPicker:v0.5"
|
implementation "com.github.DASAR:ShiftColorPicker:v0.5"
|
||||||
|
|
||||||
// Tool libraries
|
// Tool libraries
|
||||||
implementation 'commons-io:commons-io:2.6'
|
|
||||||
implementation "info.guardianproject.netcipher:netcipher:${version_library_netcipher}"
|
implementation "info.guardianproject.netcipher:netcipher:${version_library_netcipher}"
|
||||||
implementation "info.guardianproject.netcipher:netcipher-webkit:${version_library_netcipher}"
|
implementation "info.guardianproject.netcipher:netcipher-webkit:${version_library_netcipher}"
|
||||||
//noinspection AnnotationProcessorOnCompilePath
|
|
||||||
implementation "com.jakewharton:butterknife:${version_library_butterknife}"
|
implementation "com.jakewharton:butterknife:${version_library_butterknife}"
|
||||||
if (enable_plugin_kotlin) {
|
if (enable_plugin_kotlin) {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${version_plugin_kotlin}"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$version_plugin_kotlin"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processors
|
// Processors
|
||||||
|
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/flavorTest/res/drawable-ldpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
@ -15,7 +15,6 @@
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:requestLegacyExternalStorage="true"
|
|
||||||
android:theme="@style/DiasporaLight">
|
android:theme="@style/DiasporaLight">
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
|
@ -60,8 +59,7 @@
|
||||||
android:theme="@style/DiasporaLight.NoActionBar"
|
android:theme="@style/DiasporaLight.NoActionBar"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
|
||||||
<meta-data
|
<meta-data android:name="android.app.shortcuts"
|
||||||
android:name="android.app.shortcuts"
|
|
||||||
android:resource="@xml/shortcuts" />
|
android:resource="@xml/shortcuts" />
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -70,7 +68,6 @@
|
||||||
<action android:name="sc_aspects" />
|
<action android:name="sc_aspects" />
|
||||||
<action android:name="sc_activities" />
|
<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>
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
|
||||||
|
|
||||||
import net.gsantner.opoc.util.AdBlock;
|
import net.gsantner.opoc.util.AdBlock;
|
||||||
import net.gsantner.opoc.util.ContextUtils;
|
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 volatile static App app;
|
||||||
|
@ -52,7 +51,6 @@ public class App extends Application {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
ShareUtil.setFileProviderAuthority(BuildConfig.APPLICATION_ID);
|
|
||||||
app = this;
|
app = this;
|
||||||
final Context c = getApplicationContext();
|
final Context c = getApplicationContext();
|
||||||
appSettings = AppSettings.get();
|
appSettings = AppSettings.get();
|
||||||
|
@ -60,7 +58,7 @@ public class App extends Application {
|
||||||
String a = new ContextUtils(this).bcstr("FLAVOR", "");
|
String a = new ContextUtils(this).bcstr("FLAVOR", "");
|
||||||
a += "__";
|
a += "__";
|
||||||
|
|
||||||
if (appSettings.isAppFirstStart() && "flavorDandelior".equals(new ContextUtils(this).bcstr("FLAVOR", ""))) {
|
if (appSettings.isAppFirstStart() && "flavorDandelior".equals(new ContextUtils(this).bcstr("FLAVOR", ""))){
|
||||||
appSettings.setAmoledColorMode(true);
|
appSettings.setAmoledColorMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ 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());
|
ShareUtil shu = new ShareUtil(getContext()).setFileProviderAuthority(BuildConfig.APPLICATION_ID);
|
||||||
PermissionChecker permc = new PermissionChecker(getActivity());
|
PermissionChecker permc = new PermissionChecker(getActivity());
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_reload: {
|
case R.id.action_reload: {
|
||||||
|
@ -185,7 +185,7 @@ public class DiasporaStreamFragment extends BrowserFragment {
|
||||||
if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) {
|
if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) {
|
||||||
Bitmap bmp = ShareUtil.getBitmapFromWebView(webView);
|
Bitmap bmp = ShareUtil.getBitmapFromWebView(webView);
|
||||||
String filename = "dandelion-" + ShareUtil.SDF_SHORT.format(new Date()) + ".jpg";
|
String filename = "dandelion-" + ShareUtil.SDF_SHORT.format(new Date()) + ".jpg";
|
||||||
_cu.writeImageToFile(new File(fileSaveDirectory, filename), bmp);
|
_cu.writeImageToFileJpeg(new File(fileSaveDirectory, filename), bmp);
|
||||||
Snackbar.make(webView, getString(R.string.saving_screenshot_as)
|
Snackbar.make(webView, getString(R.string.saving_screenshot_as)
|
||||||
+ " " + filename, Snackbar.LENGTH_LONG).show();
|
+ " " + filename, Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ public class DiasporaStreamFragment extends BrowserFragment {
|
||||||
|
|
||||||
case R.id.action_share_screenshot: {
|
case R.id.action_share_screenshot: {
|
||||||
if (permc.doIfExtStoragePermissionGranted(getString(R.string.screenshot_permission__appspecific))) {
|
if (permc.doIfExtStoragePermissionGranted(getString(R.string.screenshot_permission__appspecific))) {
|
||||||
shu.shareImage(ShareUtil.getBitmapFromWebView(webView));
|
shu.shareImage(ShareUtil.getBitmapFromWebView(webView), Bitmap.CompressFormat.JPEG);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -565,10 +565,12 @@ public class MainActivity extends ThemedActivity
|
||||||
} else if ("sc_activities".equals(action)) {
|
} else if ("sc_activities".equals(action)) {
|
||||||
openDiasporaUrl(urls.getActivityUrl());
|
openDiasporaUrl(urls.getActivityUrl());
|
||||||
return;
|
return;
|
||||||
} else if ("sc_contacts".equals(action)) {
|
}
|
||||||
|
else if ("sc_contacts".equals(action)) {
|
||||||
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_aspects));
|
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_aspects));
|
||||||
return;
|
return;
|
||||||
} else if ("sc_tags".equals(action)) {
|
}
|
||||||
|
else if ("sc_tags".equals(action)) {
|
||||||
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_followed_tags));
|
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_followed_tags));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,8 +271,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 +279,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);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by gsantner (gsantner AT mailbox DOT org on 30.09.16.
|
* Created by gsantner (https://gsantner.net/ 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
|
||||||
|
|
|
@ -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.net/) 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;
|
||||||
|
|
|
@ -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.net/) 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 {
|
||||||
|
|
|
@ -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 (http://gsantner.net) 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";
|
||||||
|
|
|
@ -37,7 +37,7 @@ 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.net/) on 20.03.16. Part of dandelion*.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public class AppSettings extends SharedPreferencesPropertyBackend {
|
public class AppSettings extends SharedPreferencesPropertyBackend {
|
||||||
|
@ -359,14 +359,6 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
|
||||||
return getBool(R.string.pref_key__topbar_stream_shortcut, false);
|
return getBool(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(R.string.pref_key__screen_rotation, R.string.rotation_val_system);
|
||||||
}
|
}
|
||||||
|
@ -451,7 +443,6 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
|
||||||
public boolean isAmoledColorMode() {
|
public boolean isAmoledColorMode() {
|
||||||
return getBool(R.string.pref_key__primary_color__amoled_mode, false);
|
return getBool(R.string.pref_key__primary_color__amoled_mode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAmoledColorMode(boolean enable) {
|
public void setAmoledColorMode(boolean enable) {
|
||||||
setBool(R.string.pref_key__primary_color__amoled_mode, enable);
|
setBool(R.string.pref_key__primary_color__amoled_mode, enable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ 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;
|
||||||
|
@ -354,13 +353,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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ package com.github.dfa.diaspora_android.web;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.MutableContextWrapper;
|
import android.content.MutableContextWrapper;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
|
@ -51,7 +50,6 @@ 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() {
|
protected int getLayoutResId() {
|
||||||
|
@ -92,18 +90,6 @@ 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
|
||||||
|
@ -206,7 +192,6 @@ public class BrowserFragment extends ThemedFragment {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
getWebView().reload();
|
getWebView().reload();
|
||||||
swipe.setRefreshing(false);//pull to refresh
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ 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 ShareUtil shu = new ShareUtil(context).setFileProviderAuthority(BuildConfig.APPLICATION_ID);
|
||||||
final PermissionChecker permc = new PermissionChecker(parentActivity);
|
final PermissionChecker permc = new PermissionChecker(parentActivity);
|
||||||
final AppSettings appSettings = new AppSettings(context);
|
final AppSettings appSettings = new AppSettings(context);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ package com.github.dfa.diaspora_android.web;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.webkit.CookieManager;
|
import android.webkit.CookieManager;
|
||||||
|
@ -39,7 +38,6 @@ public class CustomWebViewClient extends WebViewClient {
|
||||||
private final App app;
|
private final App app;
|
||||||
private String lastLoadUrl = "";
|
private String lastLoadUrl = "";
|
||||||
private boolean isAdBlockEnabled = false;
|
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;
|
||||||
|
@ -58,11 +56,6 @@ public class CustomWebViewClient extends WebViewClient {
|
||||||
|| (host != null && (url.startsWith("https://" + host)
|
|| (host != null && (url.startsWith("https://" + host)
|
||||||
|| url.startsWith("http://" + host)))) {
|
|| url.startsWith("http://" + host)))) {
|
||||||
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);
|
||||||
|
|
|
@ -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.
|
||||||
|
* http://gsantner.net
|
||||||
*/
|
*/
|
||||||
public class WebHelper {
|
public class WebHelper {
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0 / Commercial
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
|
@ -15,15 +16,10 @@ import android.support.annotation.LayoutRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
import android.util.Log;
|
|
||||||
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 net.gsantner.opoc.android.dummy.MenuItemDummy;
|
|
||||||
import net.gsantner.opoc.util.ContextUtils;
|
import net.gsantner.opoc.util.ContextUtils;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
@ -37,7 +33,6 @@ public abstract class GsFragmentBase extends Fragment {
|
||||||
|
|
||||||
protected ContextUtils _cu;
|
protected ContextUtils _cu;
|
||||||
protected Bundle _savedInstanceState = null;
|
protected Bundle _savedInstanceState = null;
|
||||||
protected Menu _fragmentMenu = new MenuItemDummy.Menu();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -56,9 +51,6 @@ public abstract class GsFragmentBase extends Fragment {
|
||||||
_cu = new ContextUtils(inflater.getContext());
|
_cu = new ContextUtils(inflater.getContext());
|
||||||
_cu.setAppLanguage(getAppLanguage());
|
_cu.setAppLanguage(getAppLanguage());
|
||||||
_savedInstanceState = savedInstanceState;
|
_savedInstanceState = savedInstanceState;
|
||||||
if (getLayoutResId() == 0) {
|
|
||||||
Log.e(getClass().getCanonicalName(), "Error: GsFragmentbase.onCreateview: Returned 0 for getLayoutResId");
|
|
||||||
}
|
|
||||||
View view = inflater.inflate(getLayoutResId(), container, false);
|
View view = inflater.inflate(getLayoutResId(), container, false);
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
return view;
|
return view;
|
||||||
|
@ -134,27 +126,4 @@ public abstract class GsFragmentBase extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2018-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2018-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0 / Commercial
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
|
@ -124,20 +125,6 @@ public class SimpleMarkdownParser {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public final static SmpFilter FILTER_H_TO_SUP = new SmpFilter() {
|
|
||||||
@Override
|
|
||||||
public String filter(String text) {
|
|
||||||
text = text
|
|
||||||
.replace("<h1>", "<sup><sup><sup>")
|
|
||||||
.replace("</h1>", "</sup></sup></sup>")
|
|
||||||
.replace("<h2>", "<sup><sup>")
|
|
||||||
.replace("</h2>", "</sup></sup>")
|
|
||||||
.replace("<h3>", "<sup>")
|
|
||||||
.replace("</h3>", "</sup>")
|
|
||||||
;
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public final static SmpFilter FILTER_NONE = new SmpFilter() {
|
public final static SmpFilter FILTER_NONE = new SmpFilter() {
|
||||||
@Override
|
@Override
|
||||||
public String filter(String text) {
|
public String filter(String text) {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2018-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2018-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0 / Commercial
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2016-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2016-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0 / Commercial
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
|
@ -41,12 +42,9 @@ import android.support.annotation.StringRes;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,8 +57,6 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
protected static final String ARRAY_SEPARATOR = "%%%";
|
protected static final String ARRAY_SEPARATOR = "%%%";
|
||||||
protected static final String ARRAY_SEPARATOR_SUBSTITUTE = "§§§";
|
protected static final String ARRAY_SEPARATOR_SUBSTITUTE = "§§§";
|
||||||
public static final String SHARED_PREF_APP = "app";
|
public static final String SHARED_PREF_APP = "app";
|
||||||
private static String _debugLog = "";
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Members, Constructors
|
// Members, Constructors
|
||||||
|
@ -168,14 +164,6 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
return ContextCompat.getColor(_context, resColorId);
|
return ContextCompat.getColor(_context, resColorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] rstrs(int... keyResourceIds) {
|
|
||||||
String[] ret = new String[keyResourceIds.length];
|
|
||||||
for (int i = 0; i < keyResourceIds.length; i++) {
|
|
||||||
ret[i] = rstr(keyResourceIds[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Getter & Setter for String
|
// Getter & Setter for String
|
||||||
|
@ -201,15 +189,11 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString(String key, String defaultValue, final SharedPreferences... pref) {
|
public String getString(String key, String defaultValue, final SharedPreferences... pref) {
|
||||||
try {
|
return gp(pref).getString(key, defaultValue);
|
||||||
return gp(pref).getString(key, defaultValue);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString(@StringRes int keyResourceId, String defaultValue, @StringRes int keyResourceIdDefaultValue, final SharedPreferences... pref) {
|
public String getString(@StringRes int keyResourceId, String defaultValue, @StringRes int keyResourceIdDefaultValue, final SharedPreferences... pref) {
|
||||||
return getString(rstr(keyResourceId), rstr(keyResourceIdDefaultValue), pref);
|
return gp(pref).getString(rstr(keyResourceId), rstr(keyResourceIdDefaultValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStringListOne(String key, List<String> values, final SharedPreferences pref) {
|
private void setStringListOne(String key, List<String> values, final SharedPreferences pref) {
|
||||||
|
@ -223,7 +207,9 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
|
|
||||||
private ArrayList<String> getStringListOne(String key, final SharedPreferences pref) {
|
private ArrayList<String> getStringListOne(String key, final SharedPreferences pref) {
|
||||||
ArrayList<String> ret = new ArrayList<>();
|
ArrayList<String> ret = new ArrayList<>();
|
||||||
String value = getString(key, ARRAY_SEPARATOR).replace(ARRAY_SEPARATOR_SUBSTITUTE, ARRAY_SEPARATOR);
|
String value = pref
|
||||||
|
.getString(key, ARRAY_SEPARATOR)
|
||||||
|
.replace(ARRAY_SEPARATOR_SUBSTITUTE, ARRAY_SEPARATOR);
|
||||||
if (value.equals(ARRAY_SEPARATOR) || TextUtils.isEmpty(value)) {
|
if (value.equals(ARRAY_SEPARATOR) || TextUtils.isEmpty(value)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +244,6 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
return list.toArray(new String[list.size()]);
|
return list.toArray(new String[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ArrayList<String> getStringList(@StringRes int keyResourceId, final SharedPreferences... pref) {
|
public ArrayList<String> getStringList(@StringRes int keyResourceId, final SharedPreferences... pref) {
|
||||||
return getStringListOne(rstr(keyResourceId), gp(pref));
|
return getStringListOne(rstr(keyResourceId), gp(pref));
|
||||||
}
|
}
|
||||||
|
@ -279,15 +264,11 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInt(@StringRes int keyResourceId, int defaultValue, final SharedPreferences... pref) {
|
public int getInt(@StringRes int keyResourceId, int defaultValue, final SharedPreferences... pref) {
|
||||||
return getInt(rstr(keyResourceId), defaultValue, pref);
|
return gp(pref).getInt(rstr(keyResourceId), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInt(String key, int defaultValue, final SharedPreferences... pref) {
|
public int getInt(String key, int defaultValue, final SharedPreferences... pref) {
|
||||||
try {
|
return gp(pref).getInt(key, defaultValue);
|
||||||
return gp(pref).getInt(key, defaultValue);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIntOfStringPref(@StringRes int keyResId, int defaultValue, final SharedPreferences... pref) {
|
public int getIntOfStringPref(@StringRes int keyResId, int defaultValue, final SharedPreferences... pref) {
|
||||||
|
@ -310,7 +291,7 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
|
|
||||||
private ArrayList<Integer> getIntListOne(String key, final SharedPreferences pref) {
|
private ArrayList<Integer> getIntListOne(String key, final SharedPreferences pref) {
|
||||||
ArrayList<Integer> ret = new ArrayList<>();
|
ArrayList<Integer> ret = new ArrayList<>();
|
||||||
String value = getString(key, ARRAY_SEPARATOR);
|
String value = pref.getString(key, ARRAY_SEPARATOR);
|
||||||
if (value.equals(ARRAY_SEPARATOR)) {
|
if (value.equals(ARRAY_SEPARATOR)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -367,15 +348,11 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLong(@StringRes int keyResourceId, long defaultValue, final SharedPreferences... pref) {
|
public long getLong(@StringRes int keyResourceId, long defaultValue, final SharedPreferences... pref) {
|
||||||
return getLong(rstr(keyResourceId), defaultValue, pref);
|
return gp(pref).getLong(rstr(keyResourceId), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLong(String key, long defaultValue, final SharedPreferences... pref) {
|
public long getLong(String key, long defaultValue, final SharedPreferences... pref) {
|
||||||
try {
|
return gp(pref).getLong(key, defaultValue);
|
||||||
return gp(pref).getLong(key, defaultValue);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -390,15 +367,11 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getFloat(@StringRes int keyResourceId, float defaultValue, final SharedPreferences... pref) {
|
public float getFloat(@StringRes int keyResourceId, float defaultValue, final SharedPreferences... pref) {
|
||||||
return getFloat(rstr(keyResourceId), defaultValue);
|
return gp(pref).getFloat(rstr(keyResourceId), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getFloat(String key, float defaultValue, final SharedPreferences... pref) {
|
public float getFloat(String key, float defaultValue, final SharedPreferences... pref) {
|
||||||
try {
|
return gp(pref).getFloat(key, defaultValue);
|
||||||
return gp(pref).getFloat(key, defaultValue);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -432,26 +405,22 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBool(@StringRes int keyResourceId, boolean defaultValue, final SharedPreferences... pref) {
|
public boolean getBool(@StringRes int keyResourceId, boolean defaultValue, final SharedPreferences... pref) {
|
||||||
return getBool(rstr(keyResourceId), defaultValue);
|
return gp(pref).getBoolean(rstr(keyResourceId), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBool(String key, boolean defaultValue, final SharedPreferences... pref) {
|
public boolean getBool(String key, boolean defaultValue, final SharedPreferences... pref) {
|
||||||
try {
|
return gp(pref).getBoolean(key, defaultValue);
|
||||||
return gp(pref).getBoolean(key, defaultValue);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Getter & Setter for Color
|
// Getter & Setter for Color
|
||||||
//
|
//
|
||||||
public int getColor(String key, @ColorRes int defaultColor, final SharedPreferences... pref) {
|
public int getColor(String key, @ColorRes int defaultColor, final SharedPreferences... pref) {
|
||||||
return getInt(key, rcolor(defaultColor));
|
return gp(pref).getInt(key, rcolor(defaultColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getColor(@StringRes int keyResourceId, @ColorRes int defaultColor, final SharedPreferences... pref) {
|
public int getColor(@StringRes int keyResourceId, @ColorRes int defaultColor, final SharedPreferences... pref) {
|
||||||
return getColor(rstr(keyResourceId), defaultColor);
|
return gp(pref).getInt(rstr(keyResourceId), rcolor(defaultColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -545,73 +514,14 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(String key, final SharedPreferences... pref) {
|
|
||||||
return gp(pref).contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method to determine if current hour is between begin and end.
|
* A method to determine if current hour is between begin and end.
|
||||||
* This is especially useful for time-based light/dark mode
|
* This is especially useful for time-based light/dark mode
|
||||||
*/
|
*/
|
||||||
public static boolean isCurrentHourOfDayBetween(int begin, int end) {
|
public boolean isCurrentHourOfDayBetween(int begin, int end) {
|
||||||
begin = (begin >= 23 || begin < 0) ? 0 : begin;
|
begin = (begin >= 23 || begin < 0) ? 0 : begin;
|
||||||
end = (end >= 23 || end < 0) ? 0 : end;
|
end = (end >= 23 || end < 0) ? 0 : end;
|
||||||
int h = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
|
int h = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
|
||||||
return h >= begin && h <= end;
|
return h >= begin && h <= end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Substract current datetime by given amount of days
|
|
||||||
*/
|
|
||||||
public Date getDateOfDaysAgo(int days) {
|
|
||||||
Calendar cal = new GregorianCalendar();
|
|
||||||
cal.add(Calendar.DATE, -days);
|
|
||||||
return cal.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substract current datetime by given amount of days and check if the given date passed
|
|
||||||
*/
|
|
||||||
public boolean didDaysPassedSince(Date date, int days) {
|
|
||||||
if (date == null || days < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return date.before(getDateOfDaysAgo(days));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean afterDaysTrue(String key, int daysSinceLastTime, int firstTime, final SharedPreferences... pref) {
|
|
||||||
Date d = new Date(System.currentTimeMillis());
|
|
||||||
if (!contains(key)) {
|
|
||||||
d = getDateOfDaysAgo(daysSinceLastTime - firstTime);
|
|
||||||
setLong(key, d.getTime());
|
|
||||||
return firstTime < 1;
|
|
||||||
} else {
|
|
||||||
d = new Date(getLong(key, d.getTime()));
|
|
||||||
}
|
|
||||||
boolean trigger = didDaysPassedSince(d, daysSinceLastTime);
|
|
||||||
if (trigger) {
|
|
||||||
setLong(key, new Date(System.currentTimeMillis()).getTime());
|
|
||||||
}
|
|
||||||
return trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clearDebugLog() {
|
|
||||||
_debugLog = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDebugLog() {
|
|
||||||
return _debugLog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized void appendDebugLog(String text) {
|
|
||||||
_debugLog += "[" + new Date().toString() + "] " + text + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean ne(final String str) {
|
|
||||||
return str != null && !str.trim().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean fexists(final String fp) {
|
|
||||||
return ne(fp) && (new File(fp)).exists();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
|
@ -9,87 +10,44 @@
|
||||||
#########################################################*/
|
#########################################################*/
|
||||||
package net.gsantner.opoc.ui;
|
package net.gsantner.opoc.ui;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.ColorStateList;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.os.Build;
|
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.DrawableRes;
|
|
||||||
import android.support.annotation.LayoutRes;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.AppCompatEditText;
|
import android.support.v7.widget.AppCompatEditText;
|
||||||
import android.support.v7.widget.TooltipCompat;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
|
||||||
import android.text.Spannable;
|
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.Gravity;
|
import android.text.TextWatcher;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.Checkable;
|
|
||||||
import android.widget.Filter;
|
import android.widget.Filter;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import net.gsantner.opoc.android.dummy.TextWatcherDummy;
|
|
||||||
import net.gsantner.opoc.util.Callback;
|
import net.gsantner.opoc.util.Callback;
|
||||||
import net.gsantner.opoc.util.ContextUtils;
|
import net.gsantner.opoc.util.ContextUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class SearchOrCustomTextDialog {
|
public class SearchOrCustomTextDialog {
|
||||||
|
|
||||||
public static class DialogOptions {
|
public static class DialogOptions {
|
||||||
|
public Callback.a1<String> callback;
|
||||||
// Callback for search text or text of single item
|
public List<? extends CharSequence> data = new ArrayList<>();
|
||||||
@Nullable
|
public List<? extends CharSequence> highlightData = new ArrayList<>();
|
||||||
public Callback.a1<String> callback = null;
|
|
||||||
|
|
||||||
// Callback for indices of selected items.
|
|
||||||
// List will contain single item if isMultiSelectEnabled == false;
|
|
||||||
@Nullable
|
|
||||||
public Callback.a1<List<Integer>> positionCallback = null;
|
|
||||||
|
|
||||||
public boolean isMultiSelectEnabled = false;
|
|
||||||
public List<? extends CharSequence> data = null;
|
|
||||||
public List<? extends CharSequence> highlightData = null;
|
|
||||||
public List<Integer> iconsForData;
|
|
||||||
public String messageText = "";
|
public String messageText = "";
|
||||||
public String defaultText = "";
|
|
||||||
public boolean isSearchEnabled = true;
|
public boolean isSearchEnabled = true;
|
||||||
public boolean isDarkDialog = false;
|
public boolean isDarkDialog = false;
|
||||||
public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT;
|
|
||||||
public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT;
|
|
||||||
public int gravity = Gravity.NO_GRAVITY;
|
|
||||||
public int searchInputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
|
|
||||||
public boolean searchIsRegex = false;
|
|
||||||
public Callback.a1<Spannable> highlighter = null;
|
|
||||||
public String extraFilter = null;
|
|
||||||
public List<Integer> preSelected = null;
|
|
||||||
|
|
||||||
public Callback.a0 neutralButtonCallback = null;
|
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
public int textColor = 0xFF000000;
|
public int textColor = 0xFF000000;
|
||||||
|
@ -98,219 +56,124 @@ public class SearchOrCustomTextDialog {
|
||||||
@StringRes
|
@StringRes
|
||||||
public int cancelButtonText = android.R.string.cancel;
|
public int cancelButtonText = android.R.string.cancel;
|
||||||
@StringRes
|
@StringRes
|
||||||
public int neutralButtonText = 0;
|
|
||||||
@StringRes
|
|
||||||
public int okButtonText = android.R.string.ok;
|
public int okButtonText = android.R.string.ok;
|
||||||
@StringRes
|
@StringRes
|
||||||
public int titleText = 0;
|
public int titleText = android.R.string.untitled;
|
||||||
@StringRes
|
@StringRes
|
||||||
public int searchHintText = android.R.string.search_go;
|
public int searchHintText = android.R.string.search_go;
|
||||||
@DrawableRes
|
|
||||||
public int clearInputIcon = android.R.drawable.ic_input_delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Adapter extends ArrayAdapter<Integer> {
|
|
||||||
@LayoutRes
|
|
||||||
private final int _layout;
|
|
||||||
private final int _layoutHeight;
|
|
||||||
private final LayoutInflater _inflater;
|
|
||||||
private final DialogOptions _dopt;
|
|
||||||
private final List<Integer> _filteredItems;
|
|
||||||
private final Set<Integer> _selectedItems;
|
|
||||||
private final Pattern _extraPattern;
|
|
||||||
|
|
||||||
public static Adapter create(final Context context, final DialogOptions dopt) {
|
|
||||||
return new Adapter(context, dopt, dopt.isMultiSelectEnabled ? android.R.layout.simple_list_item_multiple_choice : android.R.layout.simple_list_item_1, new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Adapter(final Context context, final DialogOptions dopt, final int layout, final List<Integer> filteredItems) {
|
|
||||||
super(context, layout, filteredItems);
|
|
||||||
_layout = layout;
|
|
||||||
_filteredItems = filteredItems;
|
|
||||||
_inflater = LayoutInflater.from(context);
|
|
||||||
_dopt = dopt;
|
|
||||||
_extraPattern = (_dopt.extraFilter == null ? null : Pattern.compile(_dopt.extraFilter));
|
|
||||||
_selectedItems = new HashSet<>(_dopt.preSelected != null ? _dopt.preSelected : Collections.emptyList());
|
|
||||||
ContextUtils cu = new ContextUtils(context);
|
|
||||||
_layoutHeight = (int) cu.convertDpToPx(36);
|
|
||||||
cu.freeContextRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public View getView(int pos, @Nullable View convertView, @NonNull ViewGroup parent) {
|
|
||||||
final int index = getItem(pos);
|
|
||||||
|
|
||||||
final TextView textView;
|
|
||||||
if (convertView == null) {
|
|
||||||
textView = (TextView) _inflater.inflate(_layout, parent, false);
|
|
||||||
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
|
||||||
textView.setMinHeight(_layoutHeight);
|
|
||||||
} else {
|
|
||||||
textView = (TextView) convertView;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textView instanceof Checkable) {
|
|
||||||
((Checkable) textView).setChecked(_selectedItems.contains(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index >= 0 && _dopt.iconsForData != null && index < _dopt.iconsForData.size() && _dopt.iconsForData.get(index) != 0) {
|
|
||||||
textView.setCompoundDrawablesWithIntrinsicBounds(_dopt.iconsForData.get(index), 0, 0, 0);
|
|
||||||
textView.setCompoundDrawablePadding(32);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
textView.setCompoundDrawableTintList(ColorStateList.valueOf(_dopt.isDarkDialog ? Color.WHITE : Color.BLACK));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
final CharSequence text = _dopt.data.get(index).toString();
|
|
||||||
if (_dopt.highlightData != null) {
|
|
||||||
final boolean hl = _dopt.highlightData.contains(text);
|
|
||||||
textView.setTextColor(hl ? _dopt.highlightColor : _dopt.textColor);
|
|
||||||
textView.setTypeface(null, hl ? Typeface.BOLD : Typeface.NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_dopt.highlighter != null) {
|
|
||||||
Spannable s = new SpannableString(text);
|
|
||||||
_dopt.highlighter.callback(s);
|
|
||||||
textView.setText(s);
|
|
||||||
} else {
|
|
||||||
textView.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return textView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Filter getFilter() {
|
|
||||||
return new Filter() {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
protected void publishResults(final CharSequence constraint, final FilterResults results) {
|
|
||||||
_filteredItems.clear();
|
|
||||||
_filteredItems.addAll((List<Integer>) results.values);
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FilterResults performFiltering(final CharSequence constraint) {
|
|
||||||
final List<Integer> resList = new ArrayList<>();
|
|
||||||
|
|
||||||
if (_dopt.data != null) {
|
|
||||||
final String fil = constraint.toString();
|
|
||||||
final boolean emptySearch = fil.isEmpty();
|
|
||||||
for (int i = 0; i < _dopt.data.size(); i++) {
|
|
||||||
final String str = _dopt.data.get(i).toString();
|
|
||||||
final boolean matchExtra = (_extraPattern == null) || _extraPattern.matcher(str).find();
|
|
||||||
final Locale locale = Locale.getDefault();
|
|
||||||
final boolean matchNormal = str.toLowerCase(locale).contains(fil.toLowerCase(locale));
|
|
||||||
final boolean matchRegex = _dopt.searchIsRegex && (str.matches(fil));
|
|
||||||
if (matchExtra && (matchNormal || matchRegex || emptySearch)) {
|
|
||||||
resList.add(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final FilterResults res = new FilterResults();
|
|
||||||
res.values = resList;
|
|
||||||
res.count = resList.size();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activity, final DialogOptions dopt) {
|
public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activity, final DialogOptions dopt) {
|
||||||
|
final List<CharSequence> allItems = new ArrayList<>(dopt.data);
|
||||||
|
final List<CharSequence> filteredItems = new ArrayList<>(allItems);
|
||||||
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity, dopt.isDarkDialog
|
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity, dopt.isDarkDialog
|
||||||
? android.support.v7.appcompat.R.style.Theme_AppCompat_Dialog
|
? android.support.v7.appcompat.R.style.Theme_AppCompat_Dialog
|
||||||
: android.support.v7.appcompat.R.style.Theme_AppCompat_Light_Dialog
|
: android.support.v7.appcompat.R.style.Theme_AppCompat_Light_Dialog
|
||||||
);
|
);
|
||||||
final Adapter listAdapter = Adapter.create(activity, dopt);
|
|
||||||
|
final ArrayAdapter<CharSequence> listAdapter = new ArrayAdapter<CharSequence>(activity, android.R.layout.simple_list_item_1, filteredItems) {
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public View getView(int pos, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||||
|
TextView textView = (TextView) super.getView(pos, convertView, parent);
|
||||||
|
String text = textView.getText().toString();
|
||||||
|
|
||||||
|
boolean hl = dopt.highlightData.contains(text);
|
||||||
|
textView.setTextColor(hl ? dopt.highlightColor : dopt.textColor);
|
||||||
|
textView.setTypeface(null, hl ? Typeface.BOLD : Typeface.NORMAL);
|
||||||
|
|
||||||
|
return textView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Filter getFilter() {
|
||||||
|
return new Filter() {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected void publishResults(final CharSequence constraint, final FilterResults results) {
|
||||||
|
filteredItems.clear();
|
||||||
|
filteredItems.addAll((List<String>) results.values);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FilterResults performFiltering(final CharSequence constraint) {
|
||||||
|
final FilterResults res = new FilterResults();
|
||||||
|
final ArrayList<CharSequence> resList = new ArrayList<>();
|
||||||
|
final String fil = constraint.toString();
|
||||||
|
|
||||||
|
for (final CharSequence str : allItems) {
|
||||||
|
if ("".equals(fil) || str.toString().toLowerCase(Locale.getDefault()).contains(fil.toLowerCase(Locale.getDefault()))) {
|
||||||
|
resList.add(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.values = resList;
|
||||||
|
res.count = resList.size();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
final AppCompatEditText searchEditText = new AppCompatEditText(activity);
|
final AppCompatEditText searchEditText = new AppCompatEditText(activity);
|
||||||
searchEditText.setText(dopt.defaultText);
|
|
||||||
searchEditText.setSingleLine(true);
|
searchEditText.setSingleLine(true);
|
||||||
searchEditText.setMaxLines(1);
|
searchEditText.setMaxLines(1);
|
||||||
searchEditText.setTextColor(dopt.textColor);
|
searchEditText.setTextColor(dopt.textColor);
|
||||||
searchEditText.setHintTextColor((dopt.textColor & 0x00FFFFFF) | 0x99000000);
|
searchEditText.setHintTextColor((dopt.textColor & 0x00FFFFFF) | 0x99000000);
|
||||||
searchEditText.setHint(dopt.searchHintText);
|
searchEditText.setHint(dopt.searchHintText);
|
||||||
searchEditText.setInputType(dopt.searchInputType == 0 ? searchEditText.getInputType() : dopt.searchInputType);
|
|
||||||
searchEditText.addTextChangedListener(TextWatcherDummy.after((cbEditable) -> listAdapter.getFilter().filter(cbEditable)));
|
|
||||||
|
|
||||||
final ContextUtils cu = new ContextUtils(activity);
|
searchEditText.addTextChangedListener(new TextWatcher() {
|
||||||
final int margin = (int) cu.convertDpToPx(8);
|
@Override
|
||||||
cu.freeContextRef();
|
public void afterTextChanged(final Editable arg0) {
|
||||||
|
listAdapter.getFilter().filter(searchEditText.getText());
|
||||||
|
}
|
||||||
|
|
||||||
final LinearLayout searchLayout = new LinearLayout(activity);
|
@Override
|
||||||
searchLayout.setOrientation(LinearLayout.HORIZONTAL);
|
public void onTextChanged(final CharSequence arg0, final int arg1, final int arg2, final int arg3) {
|
||||||
|
}
|
||||||
|
|
||||||
LinearLayout.LayoutParams lp;
|
@Override
|
||||||
lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT, 1);
|
public void beforeTextChanged(final CharSequence arg0, final int arg1, final int arg2, final int arg3) {
|
||||||
lp.gravity = Gravity.START | Gravity.BOTTOM;
|
}
|
||||||
searchLayout.addView(searchEditText, lp);
|
});
|
||||||
|
|
||||||
// 'Button to clear the search box'
|
|
||||||
final ImageView clearButton = new ImageView(activity);
|
|
||||||
clearButton.setImageResource(dopt.clearInputIcon);
|
|
||||||
TooltipCompat.setTooltipText(clearButton, activity.getString(android.R.string.cancel));
|
|
||||||
clearButton.setColorFilter(dopt.isDarkDialog ? Color.WHITE : Color.parseColor("#ff505050"));
|
|
||||||
lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT, 0);
|
|
||||||
lp.gravity = Gravity.END | Gravity.CENTER_VERTICAL;
|
|
||||||
lp.setMargins(margin, 0, (int) (margin * 1.5), 0);
|
|
||||||
searchLayout.addView(clearButton, lp);
|
|
||||||
clearButton.setOnClickListener((v) -> searchEditText.setText(""));
|
|
||||||
|
|
||||||
final ListView listView = new ListView(activity);
|
final ListView listView = new ListView(activity);
|
||||||
final LinearLayout linearLayout = new LinearLayout(activity);
|
final LinearLayout linearLayout = new LinearLayout(activity);
|
||||||
listView.setAdapter(listAdapter);
|
listView.setAdapter(listAdapter);
|
||||||
listView.setVisibility(dopt.data != null && !dopt.data.isEmpty() ? View.VISIBLE : View.GONE);
|
|
||||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
if (dopt.isSearchEnabled) {
|
if (dopt.isSearchEnabled) {
|
||||||
lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
lp.setMargins(margin, margin / 2, margin, margin / 2);
|
ContextUtils cu = new net.gsantner.opoc.util.ContextUtils(listView.getContext());
|
||||||
linearLayout.addView(searchLayout, lp);
|
int px = (int) (new net.gsantner.opoc.util.ContextUtils(listView.getContext()).convertDpToPx(8));
|
||||||
|
lp.setMargins(px, px / 2, px, px / 2);
|
||||||
|
linearLayout.addView(searchEditText, lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
|
final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
|
||||||
layoutParams.weight = 1;
|
layoutParams.weight = 1;
|
||||||
linearLayout.addView(listView, layoutParams);
|
linearLayout.addView(listView, layoutParams);
|
||||||
if (!TextUtils.isEmpty(dopt.messageText)) {
|
if (!TextUtils.isEmpty(dopt.messageText)) {
|
||||||
dialogBuilder.setMessage(dopt.messageText);
|
dialogBuilder.setMessage(dopt.messageText);
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogBuilder.setView(linearLayout)
|
dialogBuilder.setView(linearLayout)
|
||||||
|
.setTitle(dopt.titleText)
|
||||||
.setOnCancelListener(null)
|
.setOnCancelListener(null)
|
||||||
.setNegativeButton(dopt.cancelButtonText, (dialogInterface, i) -> dialogInterface.dismiss());
|
.setNegativeButton(dopt.cancelButtonText, null);
|
||||||
|
if (dopt.isSearchEnabled) {
|
||||||
if (dopt.titleText != 0) {
|
|
||||||
dialogBuilder.setTitle(dopt.titleText);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok button action
|
|
||||||
if ((dopt.isSearchEnabled && dopt.callback != null) || (dopt.isMultiSelectEnabled)) {
|
|
||||||
dialogBuilder.setPositiveButton(dopt.okButtonText, (dialogInterface, i) -> {
|
dialogBuilder.setPositiveButton(dopt.okButtonText, (dialogInterface, i) -> {
|
||||||
final String searchText = dopt.isSearchEnabled ? searchEditText.getText().toString() : null;
|
dialogInterface.dismiss();
|
||||||
if (dopt.positionCallback != null && !listAdapter._selectedItems.isEmpty()) {
|
if (dopt.callback != null && !TextUtils.isEmpty(searchEditText.getText().toString())) {
|
||||||
final List<Integer> sel = new ArrayList<>(listAdapter._selectedItems);
|
dopt.callback.callback(searchEditText.getText().toString());
|
||||||
Collections.sort(sel);
|
|
||||||
dopt.positionCallback.callback(sel);
|
|
||||||
} else if (dopt.callback != null && !TextUtils.isEmpty(searchText)) {
|
|
||||||
dopt.callback.callback(searchText);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup neutralbutton
|
|
||||||
if (dopt.neutralButtonCallback != null && dopt.neutralButtonText != 0) {
|
|
||||||
dialogBuilder.setNeutralButton(dopt.neutralButtonText, (dialogInterface, i) -> {
|
|
||||||
dopt.neutralButtonCallback.callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
final AlertDialog dialog = dialogBuilder.create();
|
final AlertDialog dialog = dialogBuilder.create();
|
||||||
|
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
if (dopt.callback != null) {
|
||||||
|
dopt.callback.callback(filteredItems.get(position).toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
searchEditText.setOnKeyListener((keyView, keyCode, keyEvent) -> {
|
searchEditText.setOnKeyListener((keyView, keyCode, keyEvent) -> {
|
||||||
if ((keyEvent.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
|
if ((keyEvent.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
|
||||||
|
@ -323,72 +186,9 @@ public class SearchOrCustomTextDialog {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
Window w;
|
if (dialog.getWindow() != null) {
|
||||||
if ((w = dialog.getWindow()) != null && dopt.isSearchEnabled) {
|
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||||
w.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
|
||||||
}
|
}
|
||||||
dialog.show();
|
dialog.show();
|
||||||
if ((w = dialog.getWindow()) != null) {
|
|
||||||
int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density));
|
|
||||||
int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density));
|
|
||||||
w.setLayout(ds_w, ds_h);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((w = dialog.getWindow()) != null && dopt.gravity != Gravity.NO_GRAVITY) {
|
|
||||||
WindowManager.LayoutParams wlp = w.getAttributes();
|
|
||||||
wlp.gravity = dopt.gravity;
|
|
||||||
w.setAttributes(wlp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dopt.isSearchEnabled) {
|
|
||||||
searchEditText.requestFocus();
|
|
||||||
}
|
|
||||||
if (dopt.defaultText != null) {
|
|
||||||
listAdapter.getFilter().filter(searchEditText.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to trigger callback with single item
|
|
||||||
final Callback.b1<Integer> directActivate = (position) -> {
|
|
||||||
final int index = listAdapter._filteredItems.get(position);
|
|
||||||
dialog.dismiss();
|
|
||||||
if (dopt.callback != null) {
|
|
||||||
dopt.callback.callback(dopt.data.get(index).toString());
|
|
||||||
}
|
|
||||||
if (dopt.positionCallback != null) {
|
|
||||||
dopt.positionCallback.callback(Collections.singletonList(index));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper function to append selection count to OK button
|
|
||||||
final Button okButton = dialog.getButton(Dialog.BUTTON_POSITIVE);
|
|
||||||
final String okText = activity.getString(dopt.okButtonText) + (dopt.isMultiSelectEnabled ? " (%d)" : "");
|
|
||||||
final Callback.a0 setOkButtonState = () -> {
|
|
||||||
okButton.setText(okText.replace("%d", Integer.toString(listAdapter._selectedItems.size())));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set ok button text initially
|
|
||||||
setOkButtonState.callback();
|
|
||||||
|
|
||||||
// Item click action
|
|
||||||
listView.setOnItemClickListener((parent, textView, pos, id) -> {
|
|
||||||
if (dopt.isMultiSelectEnabled) {
|
|
||||||
final int index = listAdapter._filteredItems.get(pos);
|
|
||||||
if (listAdapter._selectedItems.contains(index)) {
|
|
||||||
listAdapter._selectedItems.remove(index);
|
|
||||||
} else {
|
|
||||||
listAdapter._selectedItems.add(index);
|
|
||||||
}
|
|
||||||
if (textView instanceof Checkable) {
|
|
||||||
((Checkable) textView).setChecked(listAdapter._selectedItems.contains(index));
|
|
||||||
}
|
|
||||||
setOkButtonState.callback();
|
|
||||||
} else {
|
|
||||||
directActivate.callback(pos);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// long click always activates
|
|
||||||
listView.setOnItemLongClickListener((parent, view, pos, id) -> directActivate.callback(pos));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2016-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2016-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
|
@ -10,18 +11,14 @@
|
||||||
package net.gsantner.opoc.util;
|
package net.gsantner.opoc.util;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
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.content.res.TypedArray;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.CalendarContract;
|
|
||||||
import android.support.annotation.ColorInt;
|
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
@ -32,16 +29,12 @@ import android.text.SpannableString;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.widget.ScrollView;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection", "rawtypes", "UnusedReturnValue"})
|
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection"})
|
||||||
public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
//########################
|
//########################
|
||||||
//## Members, Constructors
|
//## Members, Constructors
|
||||||
|
@ -53,12 +46,6 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
_activity = activity;
|
_activity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void freeContextRef() {
|
|
||||||
super.freeContextRef();
|
|
||||||
_activity = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//########################
|
//########################
|
||||||
//## Methods
|
//## Methods
|
||||||
//########################
|
//########################
|
||||||
|
@ -97,11 +84,9 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Snackbar showSnackBar(@StringRes int stringResId, boolean showLong) {
|
public void showSnackBar(@StringRes int stringResId, boolean showLong) {
|
||||||
Snackbar s = Snackbar.make(_activity.findViewById(android.R.id.content), stringResId,
|
Snackbar.make(_activity.findViewById(android.R.id.content), stringResId,
|
||||||
showLong ? Snackbar.LENGTH_LONG : Snackbar.LENGTH_SHORT);
|
showLong ? Snackbar.LENGTH_LONG : Snackbar.LENGTH_SHORT).show();
|
||||||
s.show();
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showSnackBar(@StringRes int stringResId, boolean showLong, @StringRes int actionResId, View.OnClickListener listener) {
|
public void showSnackBar(@StringRes int stringResId, boolean showLong, @StringRes int actionResId, View.OnClickListener listener) {
|
||||||
|
@ -111,58 +96,18 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityUtils setSoftKeyboardVisibile(boolean visible, View... editView) {
|
public void hideSoftKeyboard() {
|
||||||
final Activity activity = _activity;
|
InputMethodManager imm = (InputMethodManager) _activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||||
if (activity != null) {
|
if (imm != null && _activity.getCurrentFocus() != null && _activity.getCurrentFocus().getWindowToken() != null) {
|
||||||
final View v = (editView != null && editView.length > 0) ? (editView[0]) : (activity.getCurrentFocus() != null && activity.getCurrentFocus().getWindowToken() != null ? activity.getCurrentFocus() : null);
|
imm.hideSoftInputFromWindow(_activity.getCurrentFocus().getWindowToken(), 0);
|
||||||
final InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
|
||||||
if (v != null && imm != null) {
|
|
||||||
Runnable r = () -> {
|
|
||||||
if (visible) {
|
|
||||||
v.requestFocus();
|
|
||||||
imm.showSoftInput(v, InputMethodManager.SHOW_FORCED);
|
|
||||||
} else {
|
|
||||||
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
r.run();
|
|
||||||
for (int d : new int[]{100, 350}) {
|
|
||||||
v.postDelayed(r, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityUtils hideSoftKeyboard() {
|
public void showSoftKeyboard() {
|
||||||
if (_activity != null) {
|
InputMethodManager imm = (InputMethodManager) _activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||||
InputMethodManager imm = (InputMethodManager) _activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
if (imm != null && _activity.getCurrentFocus() != null && _activity.getCurrentFocus().getWindowToken() != null) {
|
||||||
if (imm != null && _activity.getCurrentFocus() != null && _activity.getCurrentFocus().getWindowToken() != null) {
|
imm.showSoftInput(_activity.getCurrentFocus(), InputMethodManager.SHOW_FORCED);
|
||||||
imm.hideSoftInputFromWindow(_activity.getCurrentFocus().getWindowToken(), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActivityUtils showSoftKeyboard() {
|
|
||||||
if (_activity != null) {
|
|
||||||
InputMethodManager imm = (InputMethodManager) _activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
|
||||||
if (imm != null && _activity.getCurrentFocus() != null && _activity.getCurrentFocus().getWindowToken() != null) {
|
|
||||||
showSoftKeyboard(_activity.getCurrentFocus());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ActivityUtils showSoftKeyboard(View textInputView) {
|
|
||||||
if (_activity != null) {
|
|
||||||
InputMethodManager imm = (InputMethodManager) _activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
|
||||||
if (imm != null && textInputView != null) {
|
|
||||||
imm.showSoftInput(textInputView, InputMethodManager.SHOW_FORCED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showDialogWithHtmlTextView(@StringRes int resTitleId, String html) {
|
public void showDialogWithHtmlTextView(@StringRes int resTitleId, String html) {
|
||||||
|
@ -170,23 +115,19 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showDialogWithHtmlTextView(@StringRes int resTitleId, String text, boolean isHtml, DialogInterface.OnDismissListener dismissedListener) {
|
public void showDialogWithHtmlTextView(@StringRes int resTitleId, String text, boolean isHtml, DialogInterface.OnDismissListener dismissedListener) {
|
||||||
ScrollView scroll = new ScrollView(_context);
|
|
||||||
AppCompatTextView textView = new AppCompatTextView(_context);
|
AppCompatTextView textView = new AppCompatTextView(_context);
|
||||||
int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, _context.getResources().getDisplayMetrics());
|
int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
|
||||||
|
_context.getResources().getDisplayMetrics());
|
||||||
scroll.setPadding(padding, 0, padding, 0);
|
|
||||||
scroll.addView(textView);
|
|
||||||
textView.setMovementMethod(new LinkMovementMethod());
|
textView.setMovementMethod(new LinkMovementMethod());
|
||||||
textView.setText(isHtml ? new SpannableString(Html.fromHtml(text)) : text);
|
textView.setPadding(padding, 0, padding, 0);
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
|
|
||||||
|
|
||||||
|
textView.setText(isHtml ? new SpannableString(Html.fromHtml(text)) : text);
|
||||||
AlertDialog.Builder dialog = new AlertDialog.Builder(_context)
|
AlertDialog.Builder dialog = new AlertDialog.Builder(_context)
|
||||||
.setPositiveButton(android.R.string.ok, null).setOnDismissListener(dismissedListener)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
.setView(scroll);
|
.setOnDismissListener(dismissedListener)
|
||||||
if (resTitleId != 0) {
|
.setTitle(resTitleId)
|
||||||
dialog.setTitle(resTitleId);
|
.setView(textView);
|
||||||
}
|
dialog.show();
|
||||||
dialogFullWidth(dialog.show(), true, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showDialogWithRawFileInWebView(String fileInRaw, @StringRes int resTitleId) {
|
public void showDialogWithRawFileInWebView(String fileInRaw, @StringRes int resTitleId) {
|
||||||
|
@ -196,11 +137,11 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
.setTitle(resTitleId)
|
.setTitle(resTitleId)
|
||||||
.setView(wv);
|
.setView(wv);
|
||||||
dialogFullWidth(dialog.show(), true, false);
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle with no param, else set visibility according to first bool
|
// Toggle with no param, else set visibility according to first bool
|
||||||
public ActivityUtils toggleStatusbarVisibility(boolean... optionalForceVisible) {
|
public void toggleStatusbarVisibility(boolean... optionalForceVisible) {
|
||||||
WindowManager.LayoutParams attrs = _activity.getWindow().getAttributes();
|
WindowManager.LayoutParams attrs = _activity.getWindow().getAttributes();
|
||||||
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||||
if (optionalForceVisible.length == 0) {
|
if (optionalForceVisible.length == 0) {
|
||||||
|
@ -211,10 +152,9 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
attrs.flags |= flag;
|
attrs.flags |= flag;
|
||||||
}
|
}
|
||||||
_activity.getWindow().setAttributes(attrs);
|
_activity.getWindow().setAttributes(attrs);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityUtils showGooglePlayEntryForThisApp() {
|
public void showGooglePlayEntryForThisApp() {
|
||||||
String pkgId = "details?id=" + _activity.getPackageName();
|
String pkgId = "details?id=" + _activity.getPackageName();
|
||||||
Intent goToMarket = new Intent(Intent.ACTION_VIEW, Uri.parse("market://" + pkgId));
|
Intent goToMarket = new Intent(Intent.ACTION_VIEW, Uri.parse("market://" + pkgId));
|
||||||
goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
|
goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
|
||||||
|
@ -224,12 +164,11 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
_activity.startActivity(goToMarket);
|
_activity.startActivity(goToMarket);
|
||||||
} catch (ActivityNotFoundException e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
_activity.startActivity(new Intent(Intent.ACTION_VIEW,
|
_activity.startActivity(new Intent(Intent.ACTION_VIEW,
|
||||||
Uri.parse("https://play.google.com/store/apps/" + pkgId)));
|
Uri.parse("http://play.google.com/store/apps/" + pkgId)));
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityUtils setStatusbarColor(int color, boolean... fromRes) {
|
public void setStatusbarColor(int color, boolean... fromRes) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
if (fromRes != null && fromRes.length > 0 && fromRes[0]) {
|
if (fromRes != null && fromRes.length > 0 && fromRes[0]) {
|
||||||
color = ContextCompat.getColor(_context, color);
|
color = ContextCompat.getColor(_context, color);
|
||||||
|
@ -237,110 +176,13 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
|
||||||
|
|
||||||
_activity.getWindow().setStatusBarColor(color);
|
_activity.getWindow().setStatusBarColor(color);
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityUtils setLauncherActivityEnabled(Class activityClass, boolean enable) {
|
public void setLauncherActivityEnabled(Class activityClass, boolean enable) {
|
||||||
try {
|
Context context = _context.getApplicationContext();
|
||||||
ComponentName component = new ComponentName(_context, activityClass);
|
PackageManager pkg = context.getPackageManager();
|
||||||
_context.getPackageManager().setComponentEnabledSetting(component, enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
|
ComponentName component = new ComponentName(context, activityClass);
|
||||||
} catch (Exception ignored) {
|
pkg.setComponentEnabledSetting(component, enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|
||||||
}
|
, PackageManager.DONT_KILL_APP);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLauncherEnabled(Class activityClass) {
|
|
||||||
try {
|
|
||||||
ComponentName component = new ComponentName(_context, activityClass);
|
|
||||||
return _context.getPackageManager().getComponentEnabledSetting(component) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
public Integer getCurrentPrimaryColor() {
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
_context.getTheme().resolveAttribute(getResId(ResType.ATTR, "colorPrimary"), typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
public Integer getCurrentPrimaryDarkColor() {
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
_context.getTheme().resolveAttribute(getResId(ResType.ATTR, "colorPrimaryDark"), typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
public Integer getCurrentAccentColor() {
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
_context.getTheme().resolveAttribute(getResId(ResType.ATTR, "colorAccent"), typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
public Integer getActivityBackgroundColor() {
|
|
||||||
TypedArray array = _activity.getTheme().obtainStyledAttributes(new int[]{
|
|
||||||
android.R.attr.colorBackground,
|
|
||||||
});
|
|
||||||
int c = array.getColor(0, 0xFF0000);
|
|
||||||
array.recycle();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActivityUtils startCalendarApp() {
|
|
||||||
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
|
|
||||||
builder.appendPath("time");
|
|
||||||
builder.appendPath(Long.toString(System.currentTimeMillis()));
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
|
|
||||||
_activity.startActivity(intent);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect if the activity is currently in splitscreen/multiwindow mode
|
|
||||||
*/
|
|
||||||
public boolean isInSplitScreenMode() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
return _activity.isInMultiWindowMode();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show dialog in full width / show keyboard
|
|
||||||
*
|
|
||||||
* @param dialog Get via dialog.show()
|
|
||||||
*/
|
|
||||||
public void dialogFullWidth(AlertDialog dialog, boolean fullWidth, boolean showKeyboard) {
|
|
||||||
try {
|
|
||||||
Window w;
|
|
||||||
if (dialog != null && (w = dialog.getWindow()) != null) {
|
|
||||||
if (fullWidth) {
|
|
||||||
w.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
|
|
||||||
}
|
|
||||||
if (showKeyboard) {
|
|
||||||
w.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make activity/app not show up in the recents history - call before finish / System.exit
|
|
||||||
public ActivityUtils removeActivityFromHistory() {
|
|
||||||
try {
|
|
||||||
ActivityManager am = (ActivityManager) _activity.getSystemService(Context.ACTIVITY_SERVICE);
|
|
||||||
if (am != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
List<ActivityManager.AppTask> tasks = am.getAppTasks();
|
|
||||||
if (tasks != null && !tasks.isEmpty()) {
|
|
||||||
tasks.get(0).setExcludeFromRecents(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License: Apache 2.0
|
* License: Apache 2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
|
@ -45,9 +46,8 @@ import java.util.Set;
|
||||||
/**
|
/**
|
||||||
* Simple Host-Based AdBlocker
|
* Simple Host-Based AdBlocker
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"WeakerAccess", "SpellCheckingInspection", "unused", "TryFinallyCanBeTryWithResources"})
|
@SuppressWarnings({"WeakerAccess", "SpellCheckingInspection", "unused"})
|
||||||
public class AdBlock {
|
public class AdBlock {
|
||||||
private static final Object synchronizeObj = new Object();
|
|
||||||
private static final AdBlock instance = new AdBlock();
|
private static final AdBlock instance = new AdBlock();
|
||||||
|
|
||||||
public static AdBlock getInstance() {
|
public static AdBlock getInstance() {
|
||||||
|
@ -61,9 +61,7 @@ public class AdBlock {
|
||||||
//########################
|
//########################
|
||||||
private final Set<String> _adblockHostsFromRaw = new HashSet<>();
|
private final Set<String> _adblockHostsFromRaw = new HashSet<>();
|
||||||
private final Set<String> _adblockHosts = new HashSet<>();
|
private final Set<String> _adblockHosts = new HashSet<>();
|
||||||
private final List<Callback.b3<URI, String, String>> _customBlockCallbacks = new ArrayList<>();
|
private boolean _isLoaded;
|
||||||
private boolean _isLoaded = false;
|
|
||||||
private boolean _isAdblockLogging = false;
|
|
||||||
|
|
||||||
//########################
|
//########################
|
||||||
//##
|
//##
|
||||||
|
@ -74,47 +72,25 @@ public class AdBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAdHost(String urlS) {
|
public boolean isAdHost(String urlS) {
|
||||||
boolean block = false;
|
|
||||||
if (urlS != null && !urlS.isEmpty() && urlS.startsWith("http")) {
|
if (urlS != null && !urlS.isEmpty() && urlS.startsWith("http")) {
|
||||||
try {
|
try {
|
||||||
URI url;
|
URI url = new URI(urlS);
|
||||||
try {
|
|
||||||
url = new URI(urlS);
|
|
||||||
} catch (Exception e) {
|
|
||||||
url = new URI(urlS.replaceFirst("[?].*", ""));
|
|
||||||
}
|
|
||||||
String host = url.getHost().trim();
|
String host = url.getHost().trim();
|
||||||
if (host.startsWith("www.") && host.length() >= 4) {
|
if (host.startsWith("www.") && host.length() >= 4) {
|
||||||
host = host.substring(4);
|
host = host.substring(4);
|
||||||
}
|
}
|
||||||
block = _adblockHosts.contains(host) || _adblockHosts.contains("www." + host);
|
return _adblockHosts.contains(host) || _adblockHosts.contains("www." + host);
|
||||||
for (Callback.b3<URI, String, String> cb : _customBlockCallbacks) {
|
|
||||||
if (block) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
block = cb.callback(url, urlS, host);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
if (_isAdblockLogging) {
|
|
||||||
Log.d(getClass().getSimpleName(), "UrlAllowed-" + (block ? "N" : "Y") + " " + urlS);
|
|
||||||
}
|
|
||||||
return block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdBlock reset() {
|
public AdBlock reset() {
|
||||||
synchronized (synchronizeObj) {
|
_adblockHosts.clear();
|
||||||
_adblockHosts.clear();
|
_adblockHosts.addAll(_adblockHostsFromRaw);
|
||||||
_adblockHosts.addAll(_adblockHostsFromRaw);
|
|
||||||
_customBlockCallbacks.clear();
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +102,7 @@ public class AdBlock {
|
||||||
return new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes()));
|
return new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdBlock addBlockedHosts(String... hosts) {
|
public void addBlockedHosts(String... hosts) {
|
||||||
for (String host : hosts) {
|
for (String host : hosts) {
|
||||||
if (host != null) {
|
if (host != null) {
|
||||||
host = host.trim();
|
host = host.trim();
|
||||||
|
@ -134,29 +110,23 @@ public class AdBlock {
|
||||||
host = host.substring(4);
|
host = host.substring(4);
|
||||||
}
|
}
|
||||||
if (!host.startsWith("#") && !host.startsWith("\"")) {
|
if (!host.startsWith("#") && !host.startsWith("\"")) {
|
||||||
synchronized (synchronizeObj) {
|
_adblockHosts.add(host);
|
||||||
_adblockHosts.add(host);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadHostsFromRawAssetsAsync(final Context context, final boolean... debugIgnoreAssets) {
|
public void loadHostsFromRawAssetsAsync(final Context context) {
|
||||||
if (debugIgnoreAssets != null && debugIgnoreAssets.length > 0 && debugIgnoreAssets[0]) {
|
new Thread(new Runnable() {
|
||||||
_isLoaded = true;
|
@Override
|
||||||
return;
|
public void run() {
|
||||||
}
|
try {
|
||||||
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
synchronized (synchronizeObj) {
|
|
||||||
loadHostsFromRawAssets(context);
|
loadHostsFromRawAssets(context);
|
||||||
_isLoaded = true;
|
_isLoaded = true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
@ -202,17 +172,4 @@ public class AdBlock {
|
||||||
}
|
}
|
||||||
return adblockResIds;
|
return adblockResIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// URI uri, String url, String host
|
|
||||||
public AdBlock addCustomBlockCallback(Callback.b3<URI, String, String> cb) {
|
|
||||||
synchronized (synchronizeObj) {
|
|
||||||
_customBlockCallbacks.add(cb);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AdBlock setLogEnabled(boolean isAdblockLogging) {
|
|
||||||
_isAdblockLogging = isAdblockLogging;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2018-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2018-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
|
@ -11,11 +12,6 @@ package net.gsantner.opoc.util;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class Callback {
|
public class Callback {
|
||||||
|
|
||||||
public interface a0 {
|
|
||||||
void callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface a1<A> {
|
public interface a1<A> {
|
||||||
void callback(A arg1);
|
void callback(A arg1);
|
||||||
}
|
}
|
||||||
|
@ -35,52 +31,4 @@ public class Callback {
|
||||||
public interface a5<A, B, C, D, E> {
|
public interface a5<A, B, C, D, E> {
|
||||||
void callback(A arg1, B arg2, C arg3, D arg4, E arg5);
|
void callback(A arg1, B arg2, C arg3, D arg4, E arg5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface b0 {
|
|
||||||
boolean callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface b1<A> {
|
|
||||||
boolean callback(A arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface b2<A, B> {
|
|
||||||
boolean callback(A arg1, B arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface b3<A, B, C> {
|
|
||||||
boolean callback(A arg1, B arg2, C arg3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface b4<A, B, C, D> {
|
|
||||||
boolean callback(A arg1, B arg2, C arg3, D arg4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface b5<A, B, C, D, E> {
|
|
||||||
boolean callback(A arg1, B arg2, C arg3, D arg4, E arg5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface s0 {
|
|
||||||
String callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface s1<A> {
|
|
||||||
String callback(A arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface s2<A, B> {
|
|
||||||
String callback(A arg1, B arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface s3<A, B, C> {
|
|
||||||
String callback(A arg1, B arg2, C arg3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface s4<A, B, C, D> {
|
|
||||||
String callback(A arg1, B arg2, C arg3, D arg4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface s5<A, B, C, D, E> {
|
|
||||||
String callback(A arg1, B arg2, C arg3, D arg4, E arg5);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2016-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2016-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
|
@ -11,11 +12,9 @@ package net.gsantner.opoc.util;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
|
@ -38,10 +37,6 @@ import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.VibrationEffect;
|
|
||||||
import android.os.Vibrator;
|
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.ColorRes;
|
import android.support.annotation.ColorRes;
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
|
@ -49,14 +44,9 @@ import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.RawRes;
|
import android.support.annotation.RawRes;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.graphics.drawable.VectorDrawableCompat;
|
import android.support.graphics.drawable.VectorDrawableCompat;
|
||||||
import android.support.v4.app.ActivityManagerCompat;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||||
import android.support.v4.text.TextUtilsCompat;
|
|
||||||
import android.support.v4.util.Pair;
|
|
||||||
import android.support.v4.view.ViewCompat;
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.InputFilter;
|
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -65,11 +55,6 @@ import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.Surface;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.webkit.MimeTypeMap;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -77,21 +62,17 @@ import net.gsantner.opoc.format.markdown.SimpleMarkdownParser;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static android.content.Context.VIBRATOR_SERVICE;
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
import static android.graphics.Bitmap.CompressFormat;
|
import static android.graphics.Bitmap.CompressFormat;
|
||||||
|
|
||||||
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection", "TryFinallyCanBeTryWithResources", "UnusedAssignment", "UnusedReturnValue"})
|
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection"})
|
||||||
public class ContextUtils {
|
public class ContextUtils {
|
||||||
//
|
//
|
||||||
// Members, Constructors
|
// Members, Constructors
|
||||||
|
@ -106,9 +87,6 @@ public class ContextUtils {
|
||||||
return _context;
|
return _context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void freeContextRef() {
|
|
||||||
_context = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class Methods
|
// Class Methods
|
||||||
|
@ -123,55 +101,39 @@ public class ContextUtils {
|
||||||
*
|
*
|
||||||
* @return A valid id if the id could be found, else 0
|
* @return A valid id if the id could be found, else 0
|
||||||
*/
|
*/
|
||||||
public int getResId(final ResType resType, final String name) {
|
public int getResId(ResType resType, final String name) {
|
||||||
try {
|
return _context.getResources().getIdentifier(name, resType.name().toLowerCase(), _context.getPackageName());
|
||||||
return _context.getResources().getIdentifier(name, resType.name().toLowerCase(), _context.getPackageName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get String by given string ressource id (nuermic)
|
* Get String by given string ressource id (nuermic)
|
||||||
*/
|
*/
|
||||||
public String rstr(@StringRes final int strResId) {
|
public String rstr(@StringRes int strResId) {
|
||||||
try {
|
return _context.getString(strResId);
|
||||||
return _context.getString(strResId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get String by given string ressource identifier (textual)
|
* Get String by given string ressource identifier (textual)
|
||||||
*/
|
*/
|
||||||
public String rstr(final String strResKey, Object... a0getResKeyAsFallback) {
|
public String rstr(String strResKey) {
|
||||||
try {
|
try {
|
||||||
return rstr(getResId(ResType.STRING, strResKey));
|
return rstr(getResId(ResType.STRING, strResKey));
|
||||||
} catch (Resources.NotFoundException e) {
|
} catch (Resources.NotFoundException e) {
|
||||||
return a0getResKeyAsFallback != null && a0getResKeyAsFallback.length > 0 ? strResKey : null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get drawable from given ressource identifier
|
* Get drawable from given ressource identifier
|
||||||
*/
|
*/
|
||||||
public Drawable rdrawable(@DrawableRes final int resId) {
|
public Drawable rdrawable(@DrawableRes int resId) {
|
||||||
try {
|
return ContextCompat.getDrawable(_context, resId);
|
||||||
return ContextCompat.getDrawable(_context, resId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get color by given color ressource id
|
* Get color by given color ressource id
|
||||||
*/
|
*/
|
||||||
public int rcolor(@ColorRes final int resId) {
|
public int rcolor(@ColorRes int resId) {
|
||||||
if (resId == 0) {
|
|
||||||
Log.e(getClass().getName(), "ContextUtils::rcolor: resId is 0!");
|
|
||||||
return Color.BLACK;
|
|
||||||
}
|
|
||||||
return ContextCompat.getColor(_context, resId);
|
return ContextCompat.getColor(_context, resId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,28 +159,20 @@ public class ContextUtils {
|
||||||
* @param intColor The color coded in int
|
* @param intColor The color coded in int
|
||||||
* @param withAlpha Optional; Set first bool parameter to true to also include alpha value
|
* @param withAlpha Optional; Set first bool parameter to true to also include alpha value
|
||||||
*/
|
*/
|
||||||
public static String colorToHexString(final int intColor, final boolean... withAlpha) {
|
public String colorToHexString(int intColor, boolean... withAlpha) {
|
||||||
boolean a = withAlpha != null && withAlpha.length >= 1 && withAlpha[0];
|
boolean a = withAlpha != null && withAlpha.length >= 1 && withAlpha[0];
|
||||||
return String.format(a ? "#%08X" : "#%06X", (a ? 0xFFFFFFFF : 0xFFFFFF) & intColor);
|
return String.format(a ? "#%08X" : "#%06X", (a ? 0xFFFFFFFF : 0xFFFFFF) & intColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAndroidVersion() {
|
|
||||||
return Build.VERSION.RELEASE + " (" + Build.VERSION.SDK_INT + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAppVersionName() {
|
public String getAppVersionName() {
|
||||||
PackageManager manager = _context.getPackageManager();
|
|
||||||
try {
|
try {
|
||||||
|
PackageManager manager = _context.getPackageManager();
|
||||||
PackageInfo info = manager.getPackageInfo(getPackageIdManifest(), 0);
|
PackageInfo info = manager.getPackageInfo(getPackageIdManifest(), 0);
|
||||||
return info.versionName;
|
return info.versionName;
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
try {
|
e.printStackTrace();
|
||||||
PackageInfo info = manager.getPackageInfo(getPackageIdReal(), 0);
|
return "?";
|
||||||
return info.versionName;
|
|
||||||
} catch (PackageManager.NameNotFoundException ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "?";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAppInstallationSource() {
|
public String getAppInstallationSource() {
|
||||||
|
@ -227,7 +181,7 @@ public class ContextUtils {
|
||||||
src = _context.getPackageManager().getInstallerPackageName(getPackageIdManifest());
|
src = _context.getPackageManager().getInstallerPackageName(getPackageIdManifest());
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
if (src == null || src.trim().isEmpty()) {
|
if (TextUtils.isEmpty(src)) {
|
||||||
return "Sideloaded";
|
return "Sideloaded";
|
||||||
} else if (src.toLowerCase().contains(".amazon.")) {
|
} else if (src.toLowerCase().contains(".amazon.")) {
|
||||||
return "Amazon Appstore";
|
return "Amazon Appstore";
|
||||||
|
@ -235,7 +189,7 @@ public class ContextUtils {
|
||||||
switch (src) {
|
switch (src) {
|
||||||
case "com.android.vending":
|
case "com.android.vending":
|
||||||
case "com.google.android.feedback": {
|
case "com.google.android.feedback": {
|
||||||
return "Google Play";
|
return "Google Play Store";
|
||||||
}
|
}
|
||||||
case "org.fdroid.fdroid.privileged":
|
case "org.fdroid.fdroid.privileged":
|
||||||
case "org.fdroid.fdroid": {
|
case "org.fdroid.fdroid": {
|
||||||
|
@ -258,16 +212,15 @@ public class ContextUtils {
|
||||||
* Send a {@link Intent#ACTION_VIEW} Intent with given paramter
|
* Send a {@link Intent#ACTION_VIEW} Intent with given paramter
|
||||||
* If the parameter is an string a browser will get triggered
|
* If the parameter is an string a browser will get triggered
|
||||||
*/
|
*/
|
||||||
public ContextUtils openWebpageInExternalBrowser(final String url) {
|
public void openWebpageInExternalBrowser(final String url) {
|
||||||
|
Uri uri = Uri.parse(url);
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||||
try {
|
try {
|
||||||
Uri uri = Uri.parse(url);
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
|
||||||
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
_context.startActivity(intent);
|
_context.startActivity(intent);
|
||||||
} catch (Exception e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,14 +228,14 @@ public class ContextUtils {
|
||||||
*/
|
*/
|
||||||
public String getPackageIdManifest() {
|
public String getPackageIdManifest() {
|
||||||
String pkg = rstr("manifest_package_id");
|
String pkg = rstr("manifest_package_id");
|
||||||
return !TextUtils.isEmpty(pkg) ? pkg : _context.getPackageName();
|
return pkg != null ? pkg : _context.getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this apps package name, returns the flavor specific package name.
|
* Get this apps package name, returns the flavor specific package name.
|
||||||
*/
|
*/
|
||||||
public String getPackageIdReal() {
|
public String getPackageIdReal() {
|
||||||
return _context.getPackageName();
|
return _context.getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -293,36 +246,23 @@ public class ContextUtils {
|
||||||
* of the package set in manifest (root element).
|
* of the package set in manifest (root element).
|
||||||
* Falls back to applicationId of the app which may differ from manifest.
|
* Falls back to applicationId of the app which may differ from manifest.
|
||||||
*/
|
*/
|
||||||
public Object getBuildConfigValue(final String fieldName) {
|
public Object getBuildConfigValue(String fieldName) {
|
||||||
final String pkg = getPackageIdManifest() + ".BuildConfig";
|
String pkg = getPackageIdManifest() + ".BuildConfig";
|
||||||
try {
|
try {
|
||||||
Class<?> c = Class.forName(pkg);
|
Class<?> c = Class.forName(pkg);
|
||||||
return c.getField(fieldName).get(null);
|
return c.getField(fieldName).get(null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getBuildConfigFields() {
|
|
||||||
final String pkg = getPackageIdManifest() + ".BuildConfig";
|
|
||||||
final List<String> fields = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
for (Field f : Class.forName(pkg).getFields()) {
|
|
||||||
fields.add(f.getName());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a BuildConfig bool value
|
* Get a BuildConfig bool value
|
||||||
*/
|
*/
|
||||||
public Boolean bcbool(final String fieldName, final Boolean defaultValue) {
|
public Boolean bcbool(String fieldName, Boolean defaultValue) {
|
||||||
Object field = getBuildConfigValue(fieldName);
|
Object field = getBuildConfigValue(fieldName);
|
||||||
if (field instanceof Boolean) {
|
if (field != null && field instanceof Boolean) {
|
||||||
return (Boolean) field;
|
return (Boolean) field;
|
||||||
}
|
}
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
@ -331,9 +271,9 @@ public class ContextUtils {
|
||||||
/**
|
/**
|
||||||
* Get a BuildConfig string value
|
* Get a BuildConfig string value
|
||||||
*/
|
*/
|
||||||
public String bcstr(final String fieldName, final String defaultValue) {
|
public String bcstr(String fieldName, String defaultValue) {
|
||||||
Object field = getBuildConfigValue(fieldName);
|
Object field = getBuildConfigValue(fieldName);
|
||||||
if (field instanceof String) {
|
if (field != null && field instanceof String) {
|
||||||
return (String) field;
|
return (String) field;
|
||||||
}
|
}
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
@ -342,9 +282,9 @@ public class ContextUtils {
|
||||||
/**
|
/**
|
||||||
* Get a BuildConfig string value
|
* Get a BuildConfig string value
|
||||||
*/
|
*/
|
||||||
public Integer bcint(final String fieldName, final int defaultValue) {
|
public Integer bcint(String fieldName, int defaultValue) {
|
||||||
Object field = getBuildConfigValue(fieldName);
|
Object field = getBuildConfigValue(fieldName);
|
||||||
if (field instanceof Integer) {
|
if (field != null && field instanceof Integer) {
|
||||||
return (Integer) field;
|
return (Integer) field;
|
||||||
}
|
}
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
@ -364,6 +304,26 @@ public class ContextUtils {
|
||||||
return bcbool("IS_FOSS_BUILD", false);
|
return bcbool("IS_FOSS_BUILD", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a bitcoin donation with given details.
|
||||||
|
* All parameters are awaited as string resource ids
|
||||||
|
*/
|
||||||
|
public void showDonateBitcoinRequest(@StringRes final int srBitcoinId, @StringRes final int srBitcoinAmount, @StringRes final int srBitcoinMessage, @StringRes final int srAlternativeDonateUrl) {
|
||||||
|
if (!isGooglePlayBuild()) {
|
||||||
|
String btcUri = String.format("bitcoin:%s?amount=%s&label=%s&message=%s",
|
||||||
|
rstr(srBitcoinId), rstr(srBitcoinAmount),
|
||||||
|
rstr(srBitcoinMessage), rstr(srBitcoinMessage));
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
|
intent.setData(Uri.parse(btcUri));
|
||||||
|
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
try {
|
||||||
|
_context.startActivity(intent);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
openWebpageInExternalBrowser(rstr(srAlternativeDonateUrl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String readTextfileFromRawRes(@RawRes int rawResId, String linePrefix, String linePostfix) {
|
public String readTextfileFromRawRes(@RawRes int rawResId, String linePrefix, String linePostfix) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
|
@ -412,8 +372,8 @@ public class ContextUtils {
|
||||||
* Check if app with given {@code packageName} is installed
|
* Check if app with given {@code packageName} is installed
|
||||||
*/
|
*/
|
||||||
public boolean isAppInstalled(String packageName) {
|
public boolean isAppInstalled(String packageName) {
|
||||||
|
PackageManager pm = _context.getApplicationContext().getPackageManager();
|
||||||
try {
|
try {
|
||||||
PackageManager pm = _context.getApplicationContext().getPackageManager();
|
|
||||||
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
|
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
|
||||||
return true;
|
return true;
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
@ -425,17 +385,17 @@ public class ContextUtils {
|
||||||
* Restart the current app. Supply the class to start on startup
|
* Restart the current app. Supply the class to start on startup
|
||||||
*/
|
*/
|
||||||
public void restartApp(Class classToStart) {
|
public void restartApp(Class classToStart) {
|
||||||
Intent intent = new Intent(_context, classToStart);
|
Intent inte = new Intent(_context, classToStart);
|
||||||
PendingIntent pendi = PendingIntent.getActivity(_context, 555, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
PendingIntent inteP = PendingIntent.getActivity(_context, 555, inte, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
AlarmManager mgr = (AlarmManager) _context.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager mgr = (AlarmManager) _context.getSystemService(Context.ALARM_SERVICE);
|
||||||
if (_context instanceof Activity) {
|
if (_context instanceof Activity) {
|
||||||
((Activity) _context).finish();
|
((Activity) _context).finish();
|
||||||
}
|
}
|
||||||
if (mgr != null) {
|
if (mgr != null) {
|
||||||
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendi);
|
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, inteP);
|
||||||
} else {
|
} else {
|
||||||
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
inte.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||||
_context.startActivity(intent);
|
_context.startActivity(inte);
|
||||||
}
|
}
|
||||||
Runtime.getRuntime().exit(0);
|
Runtime.getRuntime().exit(0);
|
||||||
}
|
}
|
||||||
|
@ -504,25 +464,19 @@ public class ContextUtils {
|
||||||
* {@code androidLC} may be in any of the forms: en, de, de-rAt
|
* {@code androidLC} may be in any of the forms: en, de, de-rAt
|
||||||
* If given an empty string, the default (system) locale gets loaded
|
* If given an empty string, the default (system) locale gets loaded
|
||||||
*/
|
*/
|
||||||
public void setAppLanguage(final String androidLC) {
|
public void setAppLanguage(String androidLC) {
|
||||||
Locale locale = getLocaleByAndroidCode(androidLC);
|
Locale locale = getLocaleByAndroidCode(androidLC);
|
||||||
locale = (locale != null && !androidLC.isEmpty()) ? locale : Resources.getSystem().getConfiguration().locale;
|
|
||||||
setLocale(locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContextUtils setLocale(final Locale locale) {
|
|
||||||
Configuration config = _context.getResources().getConfiguration();
|
Configuration config = _context.getResources().getConfiguration();
|
||||||
config.locale = (locale != null ? locale : Resources.getSystem().getConfiguration().locale);
|
config.locale = (locale != null && !androidLC.isEmpty())
|
||||||
|
? locale : Resources.getSystem().getConfiguration().locale;
|
||||||
_context.getResources().updateConfiguration(config, null);
|
_context.getResources().updateConfiguration(config, null);
|
||||||
Locale.setDefault(locale);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to guess if the color on top of the given {@code colorOnBottomInt}
|
* Try to guess if the color on top of the given {@code colorOnBottomInt}
|
||||||
* should be light or dark. Returns true if top color should be light
|
* should be light or dark. Returns true if top color should be light
|
||||||
*/
|
*/
|
||||||
public boolean shouldColorOnTopBeLight(@ColorInt final int colorOnBottomInt) {
|
public boolean shouldColorOnTopBeLight(@ColorInt int colorOnBottomInt) {
|
||||||
return 186 > (((0.299 * Color.red(colorOnBottomInt))
|
return 186 > (((0.299 * Color.red(colorOnBottomInt))
|
||||||
+ ((0.587 * Color.green(colorOnBottomInt))
|
+ ((0.587 * Color.green(colorOnBottomInt))
|
||||||
+ (0.114 * Color.blue(colorOnBottomInt)))));
|
+ (0.114 * Color.blue(colorOnBottomInt)))));
|
||||||
|
@ -531,7 +485,7 @@ public class ContextUtils {
|
||||||
/**
|
/**
|
||||||
* Convert a html string to an android {@link Spanned} object
|
* Convert a html string to an android {@link Spanned} object
|
||||||
*/
|
*/
|
||||||
public Spanned htmlToSpanned(final String html) {
|
public Spanned htmlToSpanned(String html) {
|
||||||
Spanned result;
|
Spanned result;
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||||
result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
|
result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
|
||||||
|
@ -555,87 +509,12 @@ public class ContextUtils {
|
||||||
return dp * _context.getResources().getDisplayMetrics().density;
|
return dp * _context.getResources().getDisplayMetrics().density;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the private directory for the current package (usually /data/data/package.name/)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
|
||||||
public File getAppDataPrivateDir() {
|
|
||||||
File filesDir;
|
|
||||||
try {
|
|
||||||
filesDir = new File(new File(_context.getPackageManager().getPackageInfo(getPackageIdReal(), 0).applicationInfo.dataDir), "files");
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
filesDir = _context.getFilesDir();
|
|
||||||
}
|
|
||||||
if (!filesDir.exists() && filesDir.mkdirs()) ;
|
|
||||||
return filesDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get public (accessible) appdata folders
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
|
||||||
public List<Pair<File, String>> getAppDataPublicDirs(boolean internalStorageFolder, boolean sdcardFolders, boolean storageNameWithoutType) {
|
|
||||||
List<Pair<File, String>> dirs = new ArrayList<>();
|
|
||||||
for (File externalFileDir : ContextCompat.getExternalFilesDirs(_context, null)) {
|
|
||||||
if (externalFileDir == null || Environment.getExternalStorageDirectory() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
boolean isInt = externalFileDir.getAbsolutePath().startsWith(Environment.getExternalStorageDirectory().getAbsolutePath());
|
|
||||||
boolean add = (internalStorageFolder && isInt) || (sdcardFolders && !isInt);
|
|
||||||
if (add) {
|
|
||||||
dirs.add(new Pair<>(externalFileDir, getStorageName(externalFileDir, storageNameWithoutType)));
|
|
||||||
if (!externalFileDir.exists() && externalFileDir.mkdirs()) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dirs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStorageName(final File externalFileDir, final boolean storageNameWithoutType) {
|
|
||||||
boolean isInt = externalFileDir.getAbsolutePath().startsWith(Environment.getExternalStorageDirectory().getAbsolutePath());
|
|
||||||
|
|
||||||
String[] split = externalFileDir.getAbsolutePath().split("/");
|
|
||||||
if (split.length > 2) {
|
|
||||||
return isInt ? (storageNameWithoutType ? "Internal Storage" : "") : (storageNameWithoutType ? split[2] : ("SD Card (" + split[2] + ")"));
|
|
||||||
} else {
|
|
||||||
return "Storage";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Pair<File, String>> getStorages(final boolean internalStorageFolder, final boolean sdcardFolders) {
|
|
||||||
List<Pair<File, String>> storages = new ArrayList<>();
|
|
||||||
for (Pair<File, String> pair : getAppDataPublicDirs(internalStorageFolder, sdcardFolders, true)) {
|
|
||||||
if (pair.first != null && pair.first.getAbsolutePath().lastIndexOf("/Android/data") > 0) {
|
|
||||||
try {
|
|
||||||
storages.add(new Pair<>(new File(pair.first.getCanonicalPath().replaceFirst("/Android/data.*", "")), pair.second));
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return storages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getStorageRootFolder(final File file) {
|
|
||||||
String filepath;
|
|
||||||
try {
|
|
||||||
filepath = file.getCanonicalPath();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (Pair<File, String> storage : getStorages(false, true)) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
if (filepath.startsWith(storage.first.getAbsolutePath())) {
|
|
||||||
return storage.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request the givens paths to be scanned by MediaScanner
|
* Request the givens paths to be scanned by MediaScanner
|
||||||
*
|
*
|
||||||
* @param files Files and folders to scan
|
* @param files Files and folders to scan
|
||||||
*/
|
*/
|
||||||
public void mediaScannerScanFile(final File... files) {
|
public void mediaScannerScanFile(File... files) {
|
||||||
if (android.os.Build.VERSION.SDK_INT > 19) {
|
if (android.os.Build.VERSION.SDK_INT > 19) {
|
||||||
String[] paths = new String[files.length];
|
String[] paths = new String[files.length];
|
||||||
for (int i = 0; i < files.length; i++) {
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
@ -684,12 +563,8 @@ public class ContextUtils {
|
||||||
/**
|
/**
|
||||||
* Get a {@link Bitmap} out of a {@link DrawableRes}
|
* Get a {@link Bitmap} out of a {@link DrawableRes}
|
||||||
*/
|
*/
|
||||||
public Bitmap drawableToBitmap(@DrawableRes final int drawableId) {
|
public Bitmap drawableToBitmap(@DrawableRes int drawableId) {
|
||||||
try {
|
return drawableToBitmap(ContextCompat.getDrawable(_context, drawableId));
|
||||||
return drawableToBitmap(ContextCompat.getDrawable(_context, drawableId));
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -697,7 +572,7 @@ public class ContextUtils {
|
||||||
* Specifying a {@code maxDimen} is also possible and a value below 2000
|
* Specifying a {@code maxDimen} is also possible and a value below 2000
|
||||||
* is recommended, otherwise a {@link OutOfMemoryError} may occur
|
* is recommended, otherwise a {@link OutOfMemoryError} may occur
|
||||||
*/
|
*/
|
||||||
public Bitmap loadImageFromFilesystem(final File imagePath, final int maxDimen) {
|
public Bitmap loadImageFromFilesystem(File imagePath, int maxDimen) {
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
options.inJustDecodeBounds = true;
|
options.inJustDecodeBounds = true;
|
||||||
BitmapFactory.decodeFile(imagePath.getAbsolutePath(), options);
|
BitmapFactory.decodeFile(imagePath.getAbsolutePath(), options);
|
||||||
|
@ -713,7 +588,7 @@ public class ContextUtils {
|
||||||
* @param maxDimen Max size of the Bitmap (width or height)
|
* @param maxDimen Max size of the Bitmap (width or height)
|
||||||
* @return the scaling factor that needs to be applied to the bitmap
|
* @return the scaling factor that needs to be applied to the bitmap
|
||||||
*/
|
*/
|
||||||
public int calculateInSampleSize(final BitmapFactory.Options options, final int maxDimen) {
|
public int calculateInSampleSize(BitmapFactory.Options options, int maxDimen) {
|
||||||
// Raw height and width of image
|
// Raw height and width of image
|
||||||
int height = options.outHeight;
|
int height = options.outHeight;
|
||||||
int width = options.outWidth;
|
int width = options.outWidth;
|
||||||
|
@ -729,7 +604,7 @@ public class ContextUtils {
|
||||||
* Scale the bitmap so both dimensions are lower or equal to {@code maxDimen}
|
* Scale the bitmap so both dimensions are lower or equal to {@code maxDimen}
|
||||||
* This keeps the aspect ratio
|
* This keeps the aspect ratio
|
||||||
*/
|
*/
|
||||||
public Bitmap scaleBitmap(final Bitmap bitmap, final int maxDimen) {
|
public Bitmap scaleBitmap(Bitmap bitmap, int maxDimen) {
|
||||||
int picSize = Math.min(bitmap.getHeight(), bitmap.getWidth());
|
int picSize = Math.min(bitmap.getHeight(), bitmap.getWidth());
|
||||||
float scale = 1.f * maxDimen / picSize;
|
float scale = 1.f * maxDimen / picSize;
|
||||||
Matrix matrix = new Matrix();
|
Matrix matrix = new Matrix();
|
||||||
|
@ -737,27 +612,44 @@ public class ContextUtils {
|
||||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the given {@link Bitmap} to {@code imageFile}, in {@link CompressFormat#JPEG} format
|
||||||
|
*/
|
||||||
|
public boolean writeImageToFileJpeg(File imageFile, Bitmap image) {
|
||||||
|
return writeImageToFile(imageFile, image, Bitmap.CompressFormat.JPEG, 95);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the given {@link Bitmap} to filesystem
|
* Write the given {@link Bitmap} to filesystem
|
||||||
*
|
*
|
||||||
* @param targetFile The file to be written in
|
* @param targetFile The file to be written in
|
||||||
* @param image Android {@link Bitmap}
|
* @param image The image as android {@link Bitmap}
|
||||||
|
* @param format One format of {@link CompressFormat}, null will determine based on filename
|
||||||
|
* @param quality Quality level, defaults to 95
|
||||||
* @return True if writing was successful
|
* @return True if writing was successful
|
||||||
*/
|
*/
|
||||||
public boolean writeImageToFile(final File targetFile, final Bitmap image, Integer... a0quality) {
|
public boolean writeImageToFile(File targetFile, Bitmap image, CompressFormat format, Integer quality) {
|
||||||
final int quality = (a0quality != null && a0quality.length > 0 && a0quality[0] >= 0 && a0quality[0] <= 100) ? a0quality[0] : 70;
|
|
||||||
final String lc = targetFile.getAbsolutePath().toLowerCase(Locale.ROOT);
|
|
||||||
final CompressFormat format = lc.endsWith(".webp") ? CompressFormat.WEBP : (lc.endsWith(".png") ? CompressFormat.PNG : CompressFormat.JPEG);
|
|
||||||
|
|
||||||
boolean ok = false;
|
|
||||||
File folder = new File(targetFile.getParent());
|
File folder = new File(targetFile.getParent());
|
||||||
|
if (quality == null || quality < 0 || quality > 100) {
|
||||||
|
quality = 95;
|
||||||
|
}
|
||||||
|
if (format == null) {
|
||||||
|
format = CompressFormat.JPEG;
|
||||||
|
String lc = targetFile.getAbsolutePath().toLowerCase(Locale.ROOT);
|
||||||
|
if (lc.endsWith(".png")) {
|
||||||
|
format = CompressFormat.PNG;
|
||||||
|
}
|
||||||
|
if (lc.endsWith(".webp")) {
|
||||||
|
format = CompressFormat.WEBP;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (folder.exists() || folder.mkdirs()) {
|
if (folder.exists() || folder.mkdirs()) {
|
||||||
FileOutputStream stream = null;
|
FileOutputStream stream = null;
|
||||||
try {
|
try {
|
||||||
stream = new FileOutputStream(targetFile);
|
stream = new FileOutputStream(targetFile); // overwrites this image every time
|
||||||
image.compress(format, quality, stream);
|
image.compress(format, quality, stream);
|
||||||
ok = true;
|
return true;
|
||||||
} catch (Exception ignored) {
|
} catch (FileNotFoundException ignored) {
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
|
@ -767,18 +659,14 @@ public class ContextUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
return false;
|
||||||
image.recycle();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw text in the center of the given {@link DrawableRes}
|
* Draw text in the center of the given {@link DrawableRes}
|
||||||
* This may be useful for e.g. badge counts
|
* This may be useful for e.g. badge counts
|
||||||
*/
|
*/
|
||||||
public Bitmap drawTextOnDrawable(@DrawableRes final int drawableRes, final String text, final int textSize) {
|
public Bitmap drawTextOnDrawable(@DrawableRes int drawableRes, String text, int textSize) {
|
||||||
Resources resources = _context.getResources();
|
Resources resources = _context.getResources();
|
||||||
float scale = resources.getDisplayMetrics().density;
|
float scale = resources.getDisplayMetrics().density;
|
||||||
Bitmap bitmap = drawableToBitmap(drawableRes);
|
Bitmap bitmap = drawableToBitmap(drawableRes);
|
||||||
|
@ -803,16 +691,12 @@ public class ContextUtils {
|
||||||
* Try to tint all {@link Menu}s {@link MenuItem}s with given color
|
* Try to tint all {@link Menu}s {@link MenuItem}s with given color
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public void tintMenuItems(final Menu menu, final boolean recurse, @ColorInt final int iconColor) {
|
public void tintMenuItems(Menu menu, boolean recurse, @ColorInt int iconColor) {
|
||||||
for (int i = 0; i < menu.size(); i++) {
|
for (int i = 0; i < menu.size(); i++) {
|
||||||
MenuItem item = menu.getItem(i);
|
MenuItem item = menu.getItem(i);
|
||||||
try {
|
tintDrawable(item.getIcon(), iconColor);
|
||||||
tintDrawable(item.getIcon(), iconColor);
|
if (item.hasSubMenu() && recurse) {
|
||||||
if (item.hasSubMenu() && recurse) {
|
tintMenuItems(item.getSubMenu(), recurse, iconColor);
|
||||||
tintMenuItems(item.getSubMenu(), recurse, iconColor);
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
// This should not happen at all, but may in bad menu.xml configuration
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -820,14 +704,14 @@ public class ContextUtils {
|
||||||
/**
|
/**
|
||||||
* Loads {@link Drawable} by given {@link DrawableRes} and applies a color
|
* Loads {@link Drawable} by given {@link DrawableRes} and applies a color
|
||||||
*/
|
*/
|
||||||
public Drawable tintDrawable(@DrawableRes final int drawableRes, @ColorInt final int color) {
|
public Drawable tintDrawable(@DrawableRes int drawableRes, @ColorInt int color) {
|
||||||
return tintDrawable(rdrawable(drawableRes), color);
|
return tintDrawable(rdrawable(drawableRes), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tint a {@link Drawable} with given {@code color}
|
* Tint a {@link Drawable} with given {@code color}
|
||||||
*/
|
*/
|
||||||
public Drawable tintDrawable(@Nullable Drawable drawable, @ColorInt final int color) {
|
public Drawable tintDrawable(@Nullable Drawable drawable, @ColorInt int color) {
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
drawable = DrawableCompat.wrap(drawable);
|
drawable = DrawableCompat.wrap(drawable);
|
||||||
DrawableCompat.setTint(drawable.mutate(), color);
|
DrawableCompat.setTint(drawable.mutate(), color);
|
||||||
|
@ -839,10 +723,7 @@ public class ContextUtils {
|
||||||
* Try to make icons in Toolbar/ActionBars SubMenus visible
|
* Try to make icons in Toolbar/ActionBars SubMenus visible
|
||||||
* This may not work on some devices and it maybe won't work on future android updates
|
* This may not work on some devices and it maybe won't work on future android updates
|
||||||
*/
|
*/
|
||||||
public void setSubMenuIconsVisiblity(final Menu menu, final boolean visible) {
|
public void setSubMenuIconsVisiblity(Menu menu, boolean visible) {
|
||||||
if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
|
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
|
||||||
try {
|
try {
|
||||||
@SuppressLint("PrivateApi") Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
|
@SuppressLint("PrivateApi") Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
|
||||||
|
@ -853,165 +734,4 @@ public class ContextUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getLocalizedDateFormat() {
|
|
||||||
return ((SimpleDateFormat) android.text.format.DateFormat.getDateFormat(_context)).toPattern();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLocalizedTimeFormat() {
|
|
||||||
return ((SimpleDateFormat) android.text.format.DateFormat.getTimeFormat(_context)).toPattern();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLocalizedDateTimeFormat() {
|
|
||||||
return getLocalizedDateFormat() + " " + getLocalizedTimeFormat();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link InputFilter} for filenames
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("Convert2Lambda")
|
|
||||||
public static final InputFilter INPUTFILTER_FILENAME = new InputFilter() {
|
|
||||||
public CharSequence filter(CharSequence src, int start, int end, Spanned dest, int dstart, int dend) {
|
|
||||||
if (src.length() < 1) return null;
|
|
||||||
char last = src.charAt(src.length() - 1);
|
|
||||||
String illegal = "|\\?*<\":>[]/'";
|
|
||||||
if (illegal.indexOf(last) > -1) return src.subSequence(0, src.length() - 1);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple {@link Runnable} which does a touch event on a view.
|
|
||||||
* This pops up e.g. the keyboard on a {@link android.widget.EditText}
|
|
||||||
* <p>
|
|
||||||
* Example: new Handler().postDelayed(new DoTouchView(editView), 200);
|
|
||||||
*/
|
|
||||||
public static class DoTouchView implements Runnable {
|
|
||||||
View _view;
|
|
||||||
|
|
||||||
public DoTouchView(View view) {
|
|
||||||
_view = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
_view.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
|
|
||||||
_view.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getMimeType(final File file) {
|
|
||||||
return getMimeType(Uri.fromFile(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect MimeType of given file
|
|
||||||
* Android/Java's own MimeType map is very very small and detection barely works at all
|
|
||||||
* Hence use custom map for some file extensions
|
|
||||||
*/
|
|
||||||
public String getMimeType(final Uri uri) {
|
|
||||||
String mimeType = null;
|
|
||||||
if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
|
|
||||||
ContentResolver cr = _context.getContentResolver();
|
|
||||||
mimeType = cr.getType(uri);
|
|
||||||
} else {
|
|
||||||
String filename = uri.toString();
|
|
||||||
if (filename.endsWith(".jenc")) {
|
|
||||||
filename = filename.replace(".jenc", "");
|
|
||||||
}
|
|
||||||
String ext = MimeTypeMap.getFileExtensionFromUrl(filename);
|
|
||||||
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext.toLowerCase());
|
|
||||||
|
|
||||||
// Try to guess if the recommended methods fail
|
|
||||||
if (TextUtils.isEmpty(mimeType)) {
|
|
||||||
switch (ext) {
|
|
||||||
case "md":
|
|
||||||
case "markdown":
|
|
||||||
case "mkd":
|
|
||||||
case "mdown":
|
|
||||||
case "mkdn":
|
|
||||||
case "mdwn":
|
|
||||||
case "rmd":
|
|
||||||
mimeType = "text/markdown";
|
|
||||||
break;
|
|
||||||
case "yaml":
|
|
||||||
case "yml":
|
|
||||||
mimeType = "text/yaml";
|
|
||||||
break;
|
|
||||||
case "json":
|
|
||||||
mimeType = "text/json";
|
|
||||||
break;
|
|
||||||
case "txt":
|
|
||||||
mimeType = "text/plain";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(mimeType)) {
|
|
||||||
mimeType = "*/*";
|
|
||||||
}
|
|
||||||
return mimeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer parseColor(final String colorstr) {
|
|
||||||
if (colorstr == null || colorstr.trim().isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return Color.parseColor(colorstr);
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDeviceGoodHardware() {
|
|
||||||
try {
|
|
||||||
ActivityManager activityManager = (ActivityManager) _context.getSystemService(Context.ACTIVITY_SERVICE);
|
|
||||||
return !ActivityManagerCompat.isLowRamDevice(activityManager) &&
|
|
||||||
Runtime.getRuntime().availableProcessors() >= 4 &&
|
|
||||||
activityManager.getMemoryClass() >= 128;
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vibrate device one time by given amount of time, defaulting to 50ms
|
|
||||||
// Requires <uses-permission android:name="android.permission.VIBRATE" /> in AndroidManifest to work
|
|
||||||
@SuppressWarnings("UnnecessaryReturnStatement")
|
|
||||||
@SuppressLint("MissingPermission")
|
|
||||||
public void vibrate(final int... ms) {
|
|
||||||
int ms_v = ms != null && ms.length > 0 ? ms[0] : 50;
|
|
||||||
Vibrator vibrator = ((Vibrator) _context.getSystemService(VIBRATOR_SERVICE));
|
|
||||||
if (vibrator == null) {
|
|
||||||
return;
|
|
||||||
} else if (Build.VERSION.SDK_INT >= 26) {
|
|
||||||
vibrator.vibrate(VibrationEffect.createOneShot(ms_v, VibrationEffect.DEFAULT_AMPLITUDE));
|
|
||||||
} else {
|
|
||||||
vibrator.vibrate(ms_v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if Wifi is connected. Requires these permissions in AndroidManifest:
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
||||||
*/
|
|
||||||
@SuppressLint("MissingPermission")
|
|
||||||
public boolean isWifiConnected(boolean... enabledOnly) {
|
|
||||||
final boolean doEnabledCheckOnly = enabledOnly != null && enabledOnly.length > 0 && enabledOnly[0];
|
|
||||||
final ConnectivityManager connectivityManager = (ConnectivityManager) _context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
||||||
final NetworkInfo wifiInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
|
||||||
return wifiInfo != null && (doEnabledCheckOnly ? wifiInfo.isAvailable() : wifiInfo.isConnected());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns if the device is currently in portrait orientation (landscape=false)
|
|
||||||
public boolean isDeviceOrientationPortrait() {
|
|
||||||
final int rotation = ((WindowManager) _context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getOrientation();
|
|
||||||
return (rotation == Surface.ROTATION_0) || (rotation == Surface.ROTATION_180);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
|
@ -10,14 +11,11 @@
|
||||||
package net.gsantner.opoc.util;
|
package net.gsantner.opoc.util;
|
||||||
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -30,7 +28,6 @@ import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -38,29 +35,20 @@ import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection", "deprecation", "TryFinallyCanBeTryWithResources"})
|
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection", "deprecation"})
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
// Used on methods like copyFile(src, dst)
|
// Used on methods like copyFile(src, dst)
|
||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
public static String readTextFileFast(final File file) {
|
public static String readTextFileFast(final File file) {
|
||||||
try {
|
try {
|
||||||
return new String(readCloseStreamWithSize(new FileInputStream(file), (int) file.length()));
|
return new String(readCloseBinaryStream(new FileInputStream(file)));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
System.err.println("readTextFileFast: File " + file + " not found.");
|
System.err.println("readTextFileFast: File " + file + " not found.");
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readCloseStreamWithSize(final InputStream stream, int size) {
|
|
||||||
byte[] data = new byte[size];
|
|
||||||
try (DataInputStream dis = new DataInputStream(stream)) {
|
|
||||||
dis.readFully(data);
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String readTextFile(final File file) {
|
public static String readTextFile(final File file) {
|
||||||
try {
|
try {
|
||||||
return readCloseTextStream(new FileInputStream(file));
|
return readCloseTextStream(new FileInputStream(file));
|
||||||
|
@ -242,30 +230,6 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean copyFile(final File src, final FileOutputStream os) {
|
|
||||||
InputStream is = null;
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
is = new FileInputStream(src);
|
|
||||||
byte[] buf = new byte[BUFFER_SIZE];
|
|
||||||
int len;
|
|
||||||
while ((len = is.read(buf)) > 0) {
|
|
||||||
os.write(buf, 0, len);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
if (is != null) {
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
if (os != null) {
|
|
||||||
os.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns -1 if the file did not contain any of the needles, otherwise,
|
// Returns -1 if the file did not contain any of the needles, otherwise,
|
||||||
// the index of which needle was found in the contents of the file.
|
// the index of which needle was found in the contents of the file.
|
||||||
//
|
//
|
||||||
|
@ -392,58 +356,44 @@ public class FileUtils {
|
||||||
*/
|
*/
|
||||||
public static String getMimeType(File file) {
|
public static String getMimeType(File file) {
|
||||||
String guess = null;
|
String guess = null;
|
||||||
if (file != null) {
|
if (file != null && file.exists() && file.isFile()) {
|
||||||
if (file.exists() && file.isFile()) {
|
InputStream is = null;
|
||||||
InputStream is = null;
|
try {
|
||||||
try {
|
is = new BufferedInputStream(new FileInputStream(file));
|
||||||
is = new BufferedInputStream(new FileInputStream(file));
|
guess = URLConnection.guessContentTypeFromStream(is);
|
||||||
guess = URLConnection.guessContentTypeFromStream(is);
|
} catch (IOException e) {
|
||||||
} catch (Exception ignored) {
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
} catch (Exception ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String filename = file.getName().replace(".jenc", "");
|
if (guess == null || guess.isEmpty()) {
|
||||||
int dot = filename.lastIndexOf(".") + 1;
|
guess = "*/*";
|
||||||
if (dot > 0 && dot < filename.length()) {
|
int dot = file.getName().lastIndexOf(".") + 1;
|
||||||
switch (filename.substring(dot)) {
|
if (dot > 0 && dot < file.getName().length()) {
|
||||||
case "md":
|
switch (file.getName().substring(dot)) {
|
||||||
case "markdown":
|
case "md":
|
||||||
case "mkd":
|
case "markdown":
|
||||||
case "mdown":
|
case "mkd":
|
||||||
case "mkdn":
|
case "mdown":
|
||||||
case "mdwn":
|
case "mkdn":
|
||||||
case "rmd":
|
case "mdwn":
|
||||||
guess = "text/markdown";
|
case "rmd":
|
||||||
break;
|
guess = "text/markdown";
|
||||||
case "txt":
|
break;
|
||||||
guess = "text/plain";
|
case "txt":
|
||||||
break;
|
guess = "text/plain";
|
||||||
case "webp":
|
break;
|
||||||
guess = "image/webp";
|
}
|
||||||
break;
|
|
||||||
case "jpg":
|
|
||||||
case "jpeg":
|
|
||||||
guess = "image/jpeg";
|
|
||||||
break;
|
|
||||||
case "png":
|
|
||||||
guess = "image/png";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextUtils.isEmpty(guess)) {
|
|
||||||
guess = URLConnection.guessContentTypeFromName(filename);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return guess;
|
||||||
return TextUtils.isEmpty(guess) ? "*/*" : guess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isTextFile(File file) {
|
public static boolean isTextFile(File file) {
|
||||||
|
@ -455,7 +405,7 @@ public class FileUtils {
|
||||||
* Analyze given textfile and retrieve multiple information from it
|
* Analyze given textfile and retrieve multiple information from it
|
||||||
* Information is written back to the {@link AtomicInteger} parameters
|
* Information is written back to the {@link AtomicInteger} parameters
|
||||||
*/
|
*/
|
||||||
public static void retrieveTextFileSummary(File file, AtomicInteger numCharacters, AtomicInteger numLines, AtomicInteger numWords) {
|
public static void retrieveTextFileSummary(File file, AtomicInteger numCharacters, AtomicInteger numLines) {
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
try {
|
try {
|
||||||
br = new BufferedReader(new FileReader(file));
|
br = new BufferedReader(new FileReader(file));
|
||||||
|
@ -463,15 +413,11 @@ public class FileUtils {
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
numLines.getAndIncrement();
|
numLines.getAndIncrement();
|
||||||
numCharacters.getAndSet(numCharacters.get() + line.length());
|
numCharacters.getAndSet(numCharacters.get() + line.length());
|
||||||
if (!line.equals("")) {
|
|
||||||
numWords.getAndSet(numWords.get() + line.split("\\s+").length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
numCharacters.set(-1);
|
numCharacters.set(-1);
|
||||||
numLines.set(-1);
|
numLines.set(-1);
|
||||||
numWords.set(-1);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
if (br != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -492,36 +438,7 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
String[] units = abbreviation ? new String[]{"B", "kB", "MB", "GB", "TB"} : new String[]{"Bytes", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes"};
|
String[] units = abbreviation ? new String[]{"B", "kB", "MB", "GB", "TB"} : new String[]{"Bytes", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes"};
|
||||||
int unit = (int) (Math.log10(size) / Math.log10(1024));
|
int unit = (int) (Math.log10(size) / Math.log10(1024));
|
||||||
return new DecimalFormat("#,##0.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(size / Math.pow(1024, unit)) + " " + units[unit];
|
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, unit))
|
||||||
}
|
+ " " + units[unit];
|
||||||
|
|
||||||
public static int[] getTimeDiffHMS(long now, long past) {
|
|
||||||
int[] ret = new int[3];
|
|
||||||
long diff = Math.abs(now - past);
|
|
||||||
ret[0] = (int) (diff / (1000 * 60 * 60)); // hours
|
|
||||||
ret[1] = (int) (diff / (1000 * 60)) % 60; // min
|
|
||||||
ret[2] = (int) (diff / 1000) % 60; // sec
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHumanReadableByteCountSI(final long bytes) {
|
|
||||||
if (bytes < 1000) {
|
|
||||||
return String.format(Locale.getDefault(), "%d%s", bytes, "B");
|
|
||||||
} else if (bytes < 1000000) {
|
|
||||||
return String.format(Locale.getDefault(), "%.2f%s", (bytes / 1000f), "KB");
|
|
||||||
} else if (bytes < 1000000000) {
|
|
||||||
return String.format(Locale.getDefault(), "%.2f%s", (bytes / 1000000f), "MB");
|
|
||||||
} else if (bytes < 1000000000000L) {
|
|
||||||
return String.format(Locale.getDefault(), "%.2f%s", (bytes / 1000000000f), "GB");
|
|
||||||
} else {
|
|
||||||
return String.format(Locale.getDefault(), "%.2f%s", (bytes / 1000000000000f), "TB");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File join(File file, String... childSegments) {
|
|
||||||
for (final String s : childSegments != null ? childSegments : new String[0]) {
|
|
||||||
file = new File(file, s);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
|
@ -76,7 +77,7 @@ public class NetworkUtils {
|
||||||
int written = 0;
|
int written = 0;
|
||||||
final float invLength = 1f / connection.getContentLength();
|
final float invLength = 1f / connection.getContentLength();
|
||||||
|
|
||||||
byte[] data = new byte[BUFFER_SIZE];
|
byte data[] = new byte[BUFFER_SIZE];
|
||||||
while ((count = input.read(data)) != -1) {
|
while ((count = input.read(data)) != -1) {
|
||||||
output.write(data, 0, count);
|
output.write(data, 0, count);
|
||||||
if (invLength != -1f && progressCallback != null) {
|
if (invLength != -1f && progressCallback != null) {
|
||||||
|
@ -149,7 +150,6 @@ public class NetworkUtils {
|
||||||
return performCall(url, method, data, null);
|
return performCall(url, method, data, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed")
|
|
||||||
private static String performCall(final URL url, final String method, final String data, final HttpURLConnection existingConnection) {
|
private static String performCall(final URL url, final String method, final String data, final HttpURLConnection existingConnection) {
|
||||||
try {
|
try {
|
||||||
final HttpURLConnection connection = existingConnection != null
|
final HttpURLConnection connection = existingConnection != null
|
||||||
|
@ -160,7 +160,7 @@ public class NetworkUtils {
|
||||||
if (data != null && !data.isEmpty()) {
|
if (data != null && !data.isEmpty()) {
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
final OutputStream output = connection.getOutputStream();
|
final OutputStream output = connection.getOutputStream();
|
||||||
output.write(data.getBytes(Charset.forName("UTF-8")));
|
output.write(data.getBytes(Charset.forName(UTF8)));
|
||||||
output.flush();
|
output.flush();
|
||||||
output.close();
|
output.close();
|
||||||
}
|
}
|
||||||
|
@ -220,14 +220,4 @@ public class NetworkUtils {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void httpGetAsync(final String url, final Callback.a1<String> callback) {
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
String c = NetworkUtils.performCall(url, GET);
|
|
||||||
callback.callback(c);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
/*#######################################################
|
/*#######################################################
|
||||||
*
|
*
|
||||||
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
|
* Maintained by Gregor Santner, 2017-
|
||||||
|
* https://gsantner.net/
|
||||||
*
|
*
|
||||||
* License of this file: Apache 2.0
|
* License of this file: Apache 2.0 (Commercial upon request)
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
* https://github.com/gsantner/opoc/#licensing
|
* https://github.com/gsantner/opoc/#licensing
|
||||||
*
|
*
|
||||||
#########################################################*/
|
#########################################################*/
|
||||||
package net.gsantner.opoc.util;
|
package net.gsantner.opoc.util;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -38,33 +36,22 @@ import android.provider.MediaStore;
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import android.support.v4.app.ActivityCompat;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.support.v4.content.FileProvider;
|
import android.support.v4.content.FileProvider;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.support.v4.content.pm.ShortcutInfoCompat;
|
import android.support.v4.content.pm.ShortcutInfoCompat;
|
||||||
import android.support.v4.content.pm.ShortcutManagerCompat;
|
import android.support.v4.content.pm.ShortcutManagerCompat;
|
||||||
import android.support.v4.graphics.drawable.IconCompat;
|
import android.support.v4.graphics.drawable.IconCompat;
|
||||||
import android.support.v4.provider.DocumentFile;
|
|
||||||
import android.support.v4.util.Pair;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.support.v7.preference.PreferenceManager;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -77,40 +64,27 @@ import static android.app.Activity.RESULT_OK;
|
||||||
* Also allows to parse/fetch information out of shared information.
|
* Also allows to parse/fetch information out of shared information.
|
||||||
* (M)Permissions are not checked, wrap ShareUtils methods if neccessary
|
* (M)Permissions are not checked, wrap ShareUtils methods if neccessary
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"UnusedReturnValue", "WeakerAccess", "SameParameterValue", "unused", "deprecation", "ConstantConditions", "ObsoleteSdkInt", "SpellCheckingInspection", "JavadocReference", "ConstantLocale"})
|
@SuppressWarnings({"UnusedReturnValue", "WeakerAccess", "SameParameterValue", "unused", "deprecation", "ConstantConditions", "ObsoleteSdkInt", "SpellCheckingInspection"})
|
||||||
public class ShareUtil {
|
public class ShareUtil {
|
||||||
public final static String EXTRA_FILEPATH = "real_file_path_2";
|
public final static String EXTRA_FILEPATH = "real_file_path_2";
|
||||||
public final static SimpleDateFormat SDF_RFC3339_ISH = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", Locale.getDefault());
|
public final static SimpleDateFormat SDF_RFC3339_ISH = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm", Locale.getDefault());
|
||||||
public final static SimpleDateFormat SDF_SHORT = new SimpleDateFormat("yyMMdd-HHmmss", Locale.getDefault());
|
public final static SimpleDateFormat SDF_SHORT = new SimpleDateFormat("yyMMdd-HHmm", Locale.getDefault());
|
||||||
public final static SimpleDateFormat SDF_IMAGES = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()); //20190511-230845
|
|
||||||
public final static String MIME_TEXT_PLAIN = "text/plain";
|
public final static String MIME_TEXT_PLAIN = "text/plain";
|
||||||
public final static String PREF_KEY__SAF_TREE_URI = "pref_key__saf_tree_uri";
|
|
||||||
|
|
||||||
public final static int REQUEST_CAMERA_PICTURE = 50001;
|
public final static int REQUEST_CAMERA_PICTURE = 50001;
|
||||||
public final static int REQUEST_PICK_PICTURE = 50002;
|
public final static int REQUEST_PICK_PICTURE = 50002;
|
||||||
public final static int REQUEST_SAF = 50003;
|
|
||||||
|
|
||||||
public final static int MIN_OVERWRITE_LENGTH = 5;
|
|
||||||
|
|
||||||
protected static String _lastCameraPictureFilepath;
|
protected static String _lastCameraPictureFilepath;
|
||||||
protected static String _fileProviderAuthority;
|
|
||||||
|
|
||||||
protected Context _context;
|
protected Context _context;
|
||||||
|
protected String _fileProviderAuthority;
|
||||||
protected String _chooserTitle;
|
protected String _chooserTitle;
|
||||||
|
|
||||||
public ShareUtil(final Context context) {
|
public ShareUtil(Context context) {
|
||||||
_context = context;
|
_context = context;
|
||||||
_chooserTitle = "➥";
|
_chooserTitle = "➥";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContext(final Context c) {
|
|
||||||
_context = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void freeContextRef() {
|
|
||||||
_context = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFileProviderAuthority() {
|
public String getFileProviderAuthority() {
|
||||||
if (TextUtils.isEmpty(_fileProviderAuthority)) {
|
if (TextUtils.isEmpty(_fileProviderAuthority)) {
|
||||||
throw new RuntimeException("Error at ShareUtil.getFileProviderAuthority(): No FileProvider authority provided");
|
throw new RuntimeException("Error at ShareUtil.getFileProviderAuthority(): No FileProvider authority provided");
|
||||||
|
@ -118,12 +92,13 @@ public class ShareUtil {
|
||||||
return _fileProviderAuthority;
|
return _fileProviderAuthority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setFileProviderAuthority(final String fileProviderAuthority) {
|
public ShareUtil setFileProviderAuthority(String fileProviderAuthority) {
|
||||||
_fileProviderAuthority = fileProviderAuthority;
|
_fileProviderAuthority = fileProviderAuthority;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ShareUtil setChooserTitle(final String title) {
|
public ShareUtil setChooserTitle(String title) {
|
||||||
_chooserTitle = title;
|
_chooserTitle = title;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +109,7 @@ public class ShareUtil {
|
||||||
* @param file the file
|
* @param file the file
|
||||||
* @return Uri for this file
|
* @return Uri for this file
|
||||||
*/
|
*/
|
||||||
public Uri getUriByFileProviderAuthority(final File file) {
|
public Uri getUriByFileProviderAuthority(File file) {
|
||||||
return FileProvider.getUriForFile(_context, getFileProviderAuthority(), file);
|
return FileProvider.getUriForFile(_context, getFileProviderAuthority(), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,11 +119,9 @@ public class ShareUtil {
|
||||||
* @param intent Thing to be shared
|
* @param intent Thing to be shared
|
||||||
* @param chooserText The title text for the chooser, or null for default
|
* @param chooserText The title text for the chooser, or null for default
|
||||||
*/
|
*/
|
||||||
public void showChooser(final Intent intent, final String chooserText) {
|
public void showChooser(Intent intent, String chooserText) {
|
||||||
try {
|
_context.startActivity(Intent.createChooser(intent,
|
||||||
_context.startActivity(Intent.createChooser(intent, chooserText != null ? chooserText : _chooserTitle));
|
chooserText != null ? chooserText : _chooserTitle));
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,7 +133,7 @@ public class ShareUtil {
|
||||||
* @param iconRes Icon resource for the item
|
* @param iconRes Icon resource for the item
|
||||||
* @param title Title of the item
|
* @param title Title of the item
|
||||||
*/
|
*/
|
||||||
public void createLauncherDesktopShortcut(final Intent intent, @DrawableRes final int iconRes, final String title) {
|
public void createLauncherDesktopShortcut(Intent intent, @DrawableRes int iconRes, String title) {
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
if (intent.getAction() == null) {
|
if (intent.getAction() == null) {
|
||||||
|
@ -185,7 +158,7 @@ public class ShareUtil {
|
||||||
* @param iconRes Icon resource for the item
|
* @param iconRes Icon resource for the item
|
||||||
* @param title Title of the item
|
* @param title Title of the item
|
||||||
*/
|
*/
|
||||||
public void createLauncherDesktopShortcutLegacy(final Intent intent, @DrawableRes final int iconRes, final String title) {
|
public void createLauncherDesktopShortcutLegacy(Intent intent, @DrawableRes int iconRes, String title) {
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
if (intent.getAction() == null) {
|
if (intent.getAction() == null) {
|
||||||
|
@ -206,7 +179,7 @@ public class ShareUtil {
|
||||||
* @param text The text to share
|
* @param text The text to share
|
||||||
* @param mimeType MimeType or null (uses text/plain)
|
* @param mimeType MimeType or null (uses text/plain)
|
||||||
*/
|
*/
|
||||||
public void shareText(final String text, @Nullable final String mimeType) {
|
public void shareText(String text, @Nullable String mimeType) {
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, text);
|
intent.putExtra(Intent.EXTRA_TEXT, text);
|
||||||
intent.setType(mimeType != null ? mimeType : MIME_TEXT_PLAIN);
|
intent.setType(mimeType != null ? mimeType : MIME_TEXT_PLAIN);
|
||||||
|
@ -219,7 +192,7 @@ public class ShareUtil {
|
||||||
* @param file The file to share
|
* @param file The file to share
|
||||||
* @param mimeType The files mime type
|
* @param mimeType The files mime type
|
||||||
*/
|
*/
|
||||||
public boolean shareStream(final File file, final String mimeType) {
|
public boolean shareStream(File file, String mimeType) {
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath());
|
intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath());
|
||||||
intent.setType(mimeType);
|
intent.setType(mimeType);
|
||||||
|
@ -229,30 +202,6 @@ public class ShareUtil {
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
||||||
showChooser(intent, null);
|
showChooser(intent, null);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception ignored) { // FileUriExposed(API24) / IllegalArgument
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Share the given files as stream with given mime-type
|
|
||||||
*
|
|
||||||
* @param files The files to share
|
|
||||||
* @param mimeType The files mime type. Usally * / * is the best option
|
|
||||||
*/
|
|
||||||
public boolean shareStreamMultiple(final Collection<File> files, final String mimeType) {
|
|
||||||
ArrayList<Uri> uris = new ArrayList<>();
|
|
||||||
for (File file : files) {
|
|
||||||
File uri = new File(file.toString());
|
|
||||||
uris.add(FileProvider.getUriForFile(_context, getFileProviderAuthority(), file));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
|
|
||||||
intent.setType(mimeType);
|
|
||||||
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
|
|
||||||
showChooser(intent, null);
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) { // FileUriExposed(API24) / IllegalArgument
|
} catch (Exception e) { // FileUriExposed(API24) / IllegalArgument
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -261,13 +210,14 @@ public class ShareUtil {
|
||||||
/**
|
/**
|
||||||
* Start calendar application to add new event, with given details prefilled
|
* Start calendar application to add new event, with given details prefilled
|
||||||
*/
|
*/
|
||||||
public boolean createCalendarAppointment(@Nullable final String title, @Nullable final String description, @Nullable final String location, @Nullable final Long... startAndEndTime) {
|
public void createCalendarAppointment(@Nullable String title, @Nullable String description, @Nullable String location, @Nullable Long... startAndEndTime) {
|
||||||
Intent intent = new Intent(Intent.ACTION_INSERT).setData(CalendarContract.Events.CONTENT_URI);
|
Intent intent = new Intent(Intent.ACTION_INSERT).setData(CalendarContract.Events.CONTENT_URI);
|
||||||
if (title != null) {
|
if (title != null) {
|
||||||
intent.putExtra(CalendarContract.Events.TITLE, title);
|
intent.putExtra(CalendarContract.Events.TITLE, title);
|
||||||
}
|
}
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
intent.putExtra(CalendarContract.Events.DESCRIPTION, (description.length() > 800 ? description.substring(0, 800) : description));
|
description = description.length() > 800 ? description.substring(0, 800) : description;
|
||||||
|
intent.putExtra(CalendarContract.Events.DESCRIPTION, description);
|
||||||
}
|
}
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
intent.putExtra(CalendarContract.Events.EVENT_LOCATION, location);
|
intent.putExtra(CalendarContract.Events.EVENT_LOCATION, location);
|
||||||
|
@ -280,13 +230,7 @@ public class ShareUtil {
|
||||||
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, startAndEndTime[1]);
|
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, startAndEndTime[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_context.startActivity(intent);
|
||||||
try {
|
|
||||||
_context.startActivity(intent);
|
|
||||||
return true;
|
|
||||||
} catch (ActivityNotFoundException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -294,7 +238,7 @@ public class ShareUtil {
|
||||||
*
|
*
|
||||||
* @param file The file to share
|
* @param file The file to share
|
||||||
*/
|
*/
|
||||||
public boolean viewFileInOtherApp(final File file, @Nullable final String type) {
|
public boolean viewFileInOtherApp(File file, @Nullable String type) {
|
||||||
// On some specific devices the first won't work
|
// On some specific devices the first won't work
|
||||||
Uri fileUri = null;
|
Uri fileUri = null;
|
||||||
try {
|
try {
|
||||||
|
@ -319,6 +263,17 @@ public class ShareUtil {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Share the given bitmap with given format
|
||||||
|
*
|
||||||
|
* @param bitmap Image
|
||||||
|
* @param format A {@link Bitmap.CompressFormat}, supporting JPEG,PNG,WEBP
|
||||||
|
* @return if success, true
|
||||||
|
*/
|
||||||
|
public boolean shareImage(Bitmap bitmap, Bitmap.CompressFormat format) {
|
||||||
|
return shareImage(bitmap, format, 95, "SharedImage");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Share the given bitmap with given format
|
* Share the given bitmap with given format
|
||||||
*
|
*
|
||||||
|
@ -328,36 +283,20 @@ public class ShareUtil {
|
||||||
* @param quality Quality of the exported image [0-100]
|
* @param quality Quality of the exported image [0-100]
|
||||||
* @return if success, true
|
* @return if success, true
|
||||||
*/
|
*/
|
||||||
public boolean shareImage(final Bitmap bitmap, final Integer... quality) {
|
public boolean shareImage(Bitmap bitmap, Bitmap.CompressFormat format, int quality, String imageName) {
|
||||||
try {
|
try {
|
||||||
File file = new File(_context.getCacheDir(), getFilenameWithTimestamp());
|
String ext = format.name().toLowerCase();
|
||||||
if (bitmap != null && new ContextUtils(_context).writeImageToFile(file, bitmap, quality)) {
|
File file = File.createTempFile(imageName, "." + ext.replace("jpeg", "jpg"), _context.getExternalCacheDir());
|
||||||
String x = FileUtils.getMimeType(file);
|
if (bitmap != null && new ContextUtils(_context).writeImageToFile(file, bitmap, format, quality)) {
|
||||||
shareStream(file, FileUtils.getMimeType(file));
|
shareStream(file, "image/" + ext);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a filename based off current datetime in filename (year, month, day, hour, minute, second)
|
|
||||||
* Examples: Screenshot_20210208-184301_Trebuchet.png IMG_20190511-230845.jpg
|
|
||||||
*
|
|
||||||
* @param A0prefixA1postfixA2ext All arguments are optional and default values are taken for null
|
|
||||||
* [0] = Prefix [Screenshot/IMG]
|
|
||||||
* [1] = Postfix [Trebuchet]
|
|
||||||
* [2] = File extensions [jpg/png/txt]
|
|
||||||
* @return Filename
|
|
||||||
*/
|
|
||||||
public static String getFilenameWithTimestamp(String... A0prefixA1postfixA2ext) {
|
|
||||||
final String prefix = (((A0prefixA1postfixA2ext != null && A0prefixA1postfixA2ext.length > 0 && !TextUtils.isEmpty(A0prefixA1postfixA2ext[0])) ? A0prefixA1postfixA2ext[0] : "Screenshot") + "_").trim().replaceFirst("^_$", "");
|
|
||||||
final String postfix = ("_" + ((A0prefixA1postfixA2ext != null && A0prefixA1postfixA2ext.length > 1 && !TextUtils.isEmpty(A0prefixA1postfixA2ext[1])) ? A0prefixA1postfixA2ext[1] : "")).trim().replaceFirst("^_$", "");
|
|
||||||
final String ext = (A0prefixA1postfixA2ext != null && A0prefixA1postfixA2ext.length > 2 && !TextUtils.isEmpty(A0prefixA1postfixA2ext[2])) ? A0prefixA1postfixA2ext[2] : "jpg";
|
|
||||||
return String.format("%s%s%s.%s", prefix.trim(), SDF_IMAGES.format(new Date()), postfix.trim(), ext.toLowerCase().replace(".", "").replace("jpeg", "jpg"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a {@link WebView}'s contents, also allows to create a PDF
|
* Print a {@link WebView}'s contents, also allows to create a PDF
|
||||||
*
|
*
|
||||||
|
@ -366,25 +305,18 @@ public class ShareUtil {
|
||||||
* @return {{@link PrintJob}} or null
|
* @return {{@link PrintJob}} or null
|
||||||
*/
|
*/
|
||||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||||
public PrintJob print(final WebView webview, final String jobName, final boolean... landscape) {
|
@SuppressWarnings("deprecation")
|
||||||
|
public PrintJob print(WebView webview, String jobName) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
final PrintDocumentAdapter printAdapter;
|
PrintDocumentAdapter printAdapter;
|
||||||
final PrintManager printManager = (PrintManager) _context.getSystemService(Context.PRINT_SERVICE);
|
PrintManager printManager = (PrintManager) webview.getContext().getSystemService(Context.PRINT_SERVICE);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
printAdapter = webview.createPrintDocumentAdapter(jobName);
|
printAdapter = webview.createPrintDocumentAdapter(jobName);
|
||||||
} else {
|
} else {
|
||||||
printAdapter = webview.createPrintDocumentAdapter();
|
printAdapter = webview.createPrintDocumentAdapter();
|
||||||
}
|
}
|
||||||
final PrintAttributes.Builder attrib = new PrintAttributes.Builder();
|
|
||||||
if (landscape != null && landscape.length > 0 && landscape[0]) {
|
|
||||||
attrib.setMediaSize(new PrintAttributes.MediaSize("ISO_A4", "android", 11690, 8270));
|
|
||||||
attrib.setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0));
|
|
||||||
}
|
|
||||||
if (printManager != null) {
|
if (printManager != null) {
|
||||||
try {
|
return printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build());
|
||||||
return printManager.print(jobName, printAdapter, attrib.build());
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e(getClass().getName(), "ERROR: Method called on too low Android API version");
|
Log.e(getClass().getName(), "ERROR: Method called on too low Android API version");
|
||||||
|
@ -397,7 +329,8 @@ public class ShareUtil {
|
||||||
* See {@link #print(WebView, String) print method}
|
* See {@link #print(WebView, String) print method}
|
||||||
*/
|
*/
|
||||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||||
public PrintJob createPdf(final WebView webview, final String jobName) {
|
@SuppressWarnings("deprecation")
|
||||||
|
public PrintJob createPdf(WebView webview, String jobName) {
|
||||||
return print(webview, jobName);
|
return print(webview, jobName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,21 +342,21 @@ public class ShareUtil {
|
||||||
* @return A {@link Bitmap} or null
|
* @return A {@link Bitmap} or null
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Bitmap getBitmapFromWebView(final WebView webView, final boolean... a0fullpage) {
|
public static Bitmap getBitmapFromWebView(WebView webView) {
|
||||||
try {
|
try {
|
||||||
//Measure WebView's content
|
//Measure WebView's content
|
||||||
if (a0fullpage != null && a0fullpage.length > 0 && a0fullpage[0]) {
|
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||||
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||||
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
webView.measure(widthMeasureSpec, heightMeasureSpec);
|
||||||
webView.measure(widthMeasureSpec, heightMeasureSpec);
|
webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
|
||||||
webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
//Build drawing cache and store its size
|
//Build drawing cache and store its size
|
||||||
webView.buildDrawingCache();
|
webView.buildDrawingCache();
|
||||||
|
int measuredWidth = webView.getMeasuredWidth();
|
||||||
|
int measuredHeight = webView.getMeasuredHeight();
|
||||||
|
|
||||||
//Creates the bitmap and draw WebView's content on in
|
//Creates the bitmap and draw WebView's content on in
|
||||||
Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(), webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
|
Bitmap bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
canvas.drawBitmap(bitmap, 0, bitmap.getHeight(), new Paint());
|
canvas.drawBitmap(bitmap, 0, bitmap.getHeight(), new Paint());
|
||||||
|
|
||||||
|
@ -442,7 +375,7 @@ public class ShareUtil {
|
||||||
* Replace (primary) clipboard contents with given {@code text}
|
* Replace (primary) clipboard contents with given {@code text}
|
||||||
* @param text Text to be set
|
* @param text Text to be set
|
||||||
*/
|
*/
|
||||||
public boolean setClipboard(final CharSequence text) {
|
public boolean setClipboard(CharSequence text) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||||
android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
|
android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
|
||||||
if (cm != null) {
|
if (cm != null) {
|
||||||
|
@ -453,10 +386,7 @@ public class ShareUtil {
|
||||||
android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
|
android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
|
||||||
if (cm != null) {
|
if (cm != null) {
|
||||||
ClipData clip = ClipData.newPlainText(_context.getPackageName(), text);
|
ClipData clip = ClipData.newPlainText(_context.getPackageName(), text);
|
||||||
try {
|
cm.setPrimaryClip(clip);
|
||||||
cm.setPrimaryClip(clip);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +428,7 @@ public class ShareUtil {
|
||||||
* @param callback Callback after paste try
|
* @param callback Callback after paste try
|
||||||
* @param serverOrNothing Supply one or no hastebin server. If empty, the default gets taken
|
* @param serverOrNothing Supply one or no hastebin server. If empty, the default gets taken
|
||||||
*/
|
*/
|
||||||
public void pasteOnHastebin(final String text, final Callback.a2<Boolean, String> callback, final String... serverOrNothing) {
|
public void pasteOnHastebin(final String text, final Callback.a2<Boolean, String> callback, String... serverOrNothing) {
|
||||||
final Handler handler = new Handler();
|
final Handler handler = new Handler();
|
||||||
final String server = (serverOrNothing != null && serverOrNothing.length > 0 && serverOrNothing[0] != null)
|
final String server = (serverOrNothing != null && serverOrNothing.length > 0 && serverOrNothing[0] != null)
|
||||||
? serverOrNothing[0] : "https://hastebin.com";
|
? serverOrNothing[0] : "https://hastebin.com";
|
||||||
|
@ -520,7 +450,7 @@ public class ShareUtil {
|
||||||
* @param body Body (content) text to be prefilled in the mail
|
* @param body Body (content) text to be prefilled in the mail
|
||||||
* @param to recipients to be prefilled in the mail
|
* @param to recipients to be prefilled in the mail
|
||||||
*/
|
*/
|
||||||
public void draftEmail(final String subject, final String body, final String... to) {
|
public void draftEmail(String subject, String body, String... to) {
|
||||||
Intent intent = new Intent(Intent.ACTION_SENDTO);
|
Intent intent = new Intent(Intent.ACTION_SENDTO);
|
||||||
intent.setData(Uri.parse("mailto:"));
|
intent.setData(Uri.parse("mailto:"));
|
||||||
if (subject != null) {
|
if (subject != null) {
|
||||||
|
@ -541,7 +471,7 @@ public class ShareUtil {
|
||||||
* @param receivingIntent The intent from {@link Activity#getIntent()}
|
* @param receivingIntent The intent from {@link Activity#getIntent()}
|
||||||
* @return A file or null if extraction did not succeed
|
* @return A file or null if extraction did not succeed
|
||||||
*/
|
*/
|
||||||
public File extractFileFromIntent(final Intent receivingIntent) {
|
public File extractFileFromIntent(Intent receivingIntent) {
|
||||||
String action = receivingIntent.getAction();
|
String action = receivingIntent.getAction();
|
||||||
String type = receivingIntent.getType();
|
String type = receivingIntent.getType();
|
||||||
File tmpf;
|
File tmpf;
|
||||||
|
@ -576,17 +506,6 @@ public class ShareUtil {
|
||||||
fileStr = fileStr.substring(prefix.length());
|
fileStr = fileStr.substring(prefix.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefix for External storage (/storage/emulated/0 /// /sdcard/) --> e.g. "content://com.amaze.filemanager/storage_root/file.txt" = "/sdcard/file.txt"
|
|
||||||
for (String prefix : new String[]{"external/", "media/", "storage_root/"}) {
|
|
||||||
if (fileStr.startsWith((tmps = prefix))) {
|
|
||||||
File f = new File(Uri.decode(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + fileStr.substring(tmps.length())));
|
|
||||||
if (f.exists()) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next/OwnCloud Fileprovider
|
// Next/OwnCloud Fileprovider
|
||||||
for (String fp : new String[]{"org.nextcloud.files", "org.nextcloud.beta.files", "org.owncloud.files"}) {
|
for (String fp : new String[]{"org.nextcloud.files", "org.nextcloud.beta.files", "org.owncloud.files"}) {
|
||||||
if (fileProvider.equals(fp) && fileStr.startsWith(tmps = "external_files/")) {
|
if (fileProvider.equals(fp) && fileStr.startsWith(tmps = "external_files/")) {
|
||||||
|
@ -601,17 +520,6 @@ public class ShareUtil {
|
||||||
if (fileProvider.equals("com.mi.android.globalFileexplorer.myprovider") && fileStr.startsWith(tmps = "external_files")) {
|
if (fileProvider.equals("com.mi.android.globalFileexplorer.myprovider") && fileStr.startsWith(tmps = "external_files")) {
|
||||||
return new File(Uri.decode(Environment.getExternalStorageDirectory().getAbsolutePath() + fileStr.substring(tmps.length())));
|
return new File(Uri.decode(Environment.getExternalStorageDirectory().getAbsolutePath() + fileStr.substring(tmps.length())));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileStr.startsWith(tmps = "external_files/")) {
|
|
||||||
for (String prefix : new String[]{Environment.getExternalStorageDirectory().getAbsolutePath(), "/storage", ""}) {
|
|
||||||
File f = new File(Uri.decode(prefix + "/" + fileStr.substring(tmps.length())));
|
|
||||||
if (f.exists()) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// URI Encoded paths with full path after content://package/
|
// URI Encoded paths with full path after content://package/
|
||||||
if (fileStr.startsWith("/") || fileStr.startsWith("%2F")) {
|
if (fileStr.startsWith("/") || fileStr.startsWith("%2F")) {
|
||||||
tmpf = new File(Uri.decode(fileStr));
|
tmpf = new File(Uri.decode(fileStr));
|
||||||
|
@ -642,16 +550,7 @@ public class ShareUtil {
|
||||||
throw new RuntimeException("Error: ShareUtil.requestGalleryPicture needs an Activity Context.");
|
throw new RuntimeException("Error: ShareUtil.requestGalleryPicture needs an Activity Context.");
|
||||||
}
|
}
|
||||||
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
try {
|
((Activity) _context).startActivityForResult(intent, REQUEST_PICK_PICTURE);
|
||||||
((Activity) _context).startActivityForResult(intent, REQUEST_PICK_PICTURE);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Toast.makeText(_context, "No gallery app installed!", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String extractFileFromIntentStr(final Intent receivingIntent) {
|
|
||||||
File f = extractFileFromIntent(receivingIntent);
|
|
||||||
return f != null ? f.getAbsolutePath() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -659,13 +558,12 @@ public class ShareUtil {
|
||||||
* Result ({@link String}) will be available from {@link Activity#onActivityResult(int, int, Intent)}.
|
* Result ({@link String}) will be available from {@link Activity#onActivityResult(int, int, Intent)}.
|
||||||
* It has set resultCode to {@link Activity#RESULT_OK} with same requestCode, if successfully
|
* It has set resultCode to {@link Activity#RESULT_OK} with same requestCode, if successfully
|
||||||
* The requested image savepath has to be stored at caller side (not contained in intent),
|
* The requested image savepath has to be stored at caller side (not contained in intent),
|
||||||
* it can be retrieved using {@link #extractResultFromActivityResult(int, int, Intent, Activity...)}
|
* it can be retrieved using {@link #extractResultFromActivityResult(int, int, Intent)},
|
||||||
* returns null if an error happened.
|
* returns null if an error happened.
|
||||||
*
|
*
|
||||||
* @param target Path to file to write to, if folder the filename gets app_name + millis + random filename. If null DCIM folder is used.
|
* @param target Path to file to write to, if folder the filename gets app_name + millis + random filename. If null DCIM folder is used.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("RegExpRedundantEscape")
|
public String requestCameraPicture(File target) {
|
||||||
public String requestCameraPicture(final File target) {
|
|
||||||
if (!(_context instanceof Activity)) {
|
if (!(_context instanceof Activity)) {
|
||||||
throw new RuntimeException("Error: ShareUtil.requestCameraPicture needs an Activity Context.");
|
throw new RuntimeException("Error: ShareUtil.requestCameraPicture needs an Activity Context.");
|
||||||
}
|
}
|
||||||
|
@ -678,7 +576,7 @@ public class ShareUtil {
|
||||||
if (target != null && !target.isDirectory()) {
|
if (target != null && !target.isDirectory()) {
|
||||||
photoFile = target;
|
photoFile = target;
|
||||||
} else {
|
} else {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", Locale.ENGLISH);
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", Locale.getDefault());
|
||||||
File storageDir = target != null ? target : new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");
|
File storageDir = target != null ? target : new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");
|
||||||
String imageFileName = ((new ContextUtils(_context).rstr("app_name")).replaceAll("[^a-zA-Z0-9\\.\\-]", "_") + "_").replace("__", "_") + sdf.format(new Date());
|
String imageFileName = ((new ContextUtils(_context).rstr("app_name")).replaceAll("[^a-zA-Z0-9\\.\\-]", "_") + "_").replace("__", "_") + sdf.format(new Date());
|
||||||
photoFile = new File(storageDir, imageFileName + ".jpg");
|
photoFile = new File(storageDir, imageFileName + ".jpg");
|
||||||
|
@ -716,9 +614,7 @@ public class ShareUtil {
|
||||||
* Forward all arguments from activity. Only requestCodes from {@link ShareUtil} get analyzed.
|
* Forward all arguments from activity. Only requestCodes from {@link ShareUtil} get analyzed.
|
||||||
* Also may forward results via local broadcast
|
* Also may forward results via local broadcast
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ApplySharedPref")
|
public Object extractResultFromActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
public Object extractResultFromActivityResult(final int requestCode, final int resultCode, final Intent data, final Activity... activityOrNull) {
|
|
||||||
Activity activity = greedyGetActivity(activityOrNull);
|
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CAMERA_PICTURE: {
|
case REQUEST_CAMERA_PICTURE: {
|
||||||
String picturePath = (resultCode == RESULT_OK) ? _lastCameraPictureFilepath : null;
|
String picturePath = (resultCode == RESULT_OK) ? _lastCameraPictureFilepath : null;
|
||||||
|
@ -748,10 +644,6 @@ public class ShareUtil {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to grab via file extraction method
|
|
||||||
data.setAction(Intent.ACTION_VIEW);
|
|
||||||
picturePath = picturePath != null ? picturePath : extractFileFromIntentStr(data);
|
|
||||||
|
|
||||||
// Retrieve image from file descriptor / Cloud, e.g.: Google Drive, Picasa
|
// Retrieve image from file descriptor / Cloud, e.g.: Google Drive, Picasa
|
||||||
if (picturePath == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (picturePath == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
try {
|
try {
|
||||||
|
@ -777,18 +669,6 @@ public class ShareUtil {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case REQUEST_SAF: {
|
|
||||||
if (resultCode == RESULT_OK && data != null && data.getData() != null) {
|
|
||||||
Uri treeUri = data.getData();
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(_context).edit().putString(PREF_KEY__SAF_TREE_URI, treeUri.toString()).commit();
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
activity.getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
}
|
|
||||||
return treeUri;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -797,7 +677,7 @@ public class ShareUtil {
|
||||||
* Send a local broadcast (to receive within app), with given action and string-extra+value.
|
* Send a local broadcast (to receive within app), with given action and string-extra+value.
|
||||||
* This is a convenience method for quickly sending just one thing.
|
* This is a convenience method for quickly sending just one thing.
|
||||||
*/
|
*/
|
||||||
public void sendLocalBroadcastWithStringExtra(final String action, final String extra, final CharSequence value) {
|
public void sendLocalBroadcastWithStringExtra(String action, String extra, CharSequence value) {
|
||||||
Intent intent = new Intent(action);
|
Intent intent = new Intent(action);
|
||||||
intent.putExtra(extra, value);
|
intent.putExtra(extra, value);
|
||||||
LocalBroadcastManager.getInstance(_context).sendBroadcast(intent);
|
LocalBroadcastManager.getInstance(_context).sendBroadcast(intent);
|
||||||
|
@ -811,7 +691,7 @@ public class ShareUtil {
|
||||||
* @param filterActions All {@link IntentFilter} actions to filter for
|
* @param filterActions All {@link IntentFilter} actions to filter for
|
||||||
* @return The created instance. Has to be unregistered on {@link Activity} lifecycle events.
|
* @return The created instance. Has to be unregistered on {@link Activity} lifecycle events.
|
||||||
*/
|
*/
|
||||||
public BroadcastReceiver receiveResultFromLocalBroadcast(final Callback.a2<Intent, BroadcastReceiver> callback, final boolean autoUnregister, final String... filterActions) {
|
public BroadcastReceiver receiveResultFromLocalBroadcast(Callback.a2<Intent, BroadcastReceiver> callback, boolean autoUnregister, String... filterActions) {
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
for (String filterAction : filterActions) {
|
for (String filterAction : filterActions) {
|
||||||
intentFilter.addAction(filterAction);
|
intentFilter.addAction(filterAction);
|
||||||
|
@ -839,7 +719,7 @@ public class ShareUtil {
|
||||||
*
|
*
|
||||||
* @param file File that should be edited
|
* @param file File that should be edited
|
||||||
*/
|
*/
|
||||||
public void requestPictureEdit(final File file) {
|
public void requestPictureEdit(File file) {
|
||||||
Uri uri = getUriByFileProviderAuthority(file);
|
Uri uri = getUriByFileProviderAuthority(file);
|
||||||
int flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
int flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
|
|
||||||
|
@ -861,10 +741,9 @@ public class ShareUtil {
|
||||||
*
|
*
|
||||||
* @param file Target file
|
* @param file Target file
|
||||||
* @param mode 1 for picture, 2 for video, anything else for other
|
* @param mode 1 for picture, 2 for video, anything else for other
|
||||||
* @return Media URI
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("TryFinallyCanBeTryWithResources")
|
public Uri getMediaUri(File file, int mode) {
|
||||||
public Uri getMediaUri(final File file, final int mode) {
|
|
||||||
Uri uri = MediaStore.Files.getContentUri("external");
|
Uri uri = MediaStore.Files.getContentUri("external");
|
||||||
uri = (mode != 0) ? (mode == 1 ? MediaStore.Images.Media.EXTERNAL_CONTENT_URI : MediaStore.Video.Media.EXTERNAL_CONTENT_URI) : uri;
|
uri = (mode != 0) ? (mode == 1 ? MediaStore.Images.Media.EXTERNAL_CONTENT_URI : MediaStore.Video.Media.EXTERNAL_CONTENT_URI) : uri;
|
||||||
|
|
||||||
|
@ -883,333 +762,4 @@ public class ShareUtil {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* By default Chrome Custom Tabs only uses Chrome Stable to open links
|
|
||||||
* There are also other packages (like Chrome Beta, Chromium, Firefox, ..)
|
|
||||||
* which implement the Chrome Custom Tab interface. This method changes
|
|
||||||
* the customtab intent to use an available compatible browser, if available.
|
|
||||||
*/
|
|
||||||
public void enableChromeCustomTabsForOtherBrowsers(final Intent customTabIntent) {
|
|
||||||
String[] checkpkgs = new String[]{
|
|
||||||
"com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.google.android.apps.chrome", "org.chromium.chrome",
|
|
||||||
"org.mozilla.fennec_fdroid", "org.mozilla.firefox", "org.mozilla.firefox_beta", "org.mozilla.fennec_aurora",
|
|
||||||
"org.mozilla.klar", "org.mozilla.focus",
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get all intent handlers for web links
|
|
||||||
PackageManager pm = _context.getPackageManager();
|
|
||||||
Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"));
|
|
||||||
List<String> browsers = new ArrayList<>();
|
|
||||||
for (ResolveInfo ri : pm.queryIntentActivities(urlIntent, 0)) {
|
|
||||||
Intent i = new Intent("android.support.customtabs.action.CustomTabsService");
|
|
||||||
i.setPackage(ri.activityInfo.packageName);
|
|
||||||
if (pm.resolveService(i, 0) != null) {
|
|
||||||
browsers.add(ri.activityInfo.packageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the user has a "default browser" selected
|
|
||||||
ResolveInfo ri = pm.resolveActivity(urlIntent, 0);
|
|
||||||
String userDefaultBrowser = (ri == null) ? null : ri.activityInfo.packageName;
|
|
||||||
|
|
||||||
// Select which browser to use out of all installed customtab supporting browsers
|
|
||||||
String pkg = null;
|
|
||||||
if (browsers.isEmpty()) {
|
|
||||||
pkg = null;
|
|
||||||
} else if (browsers.size() == 1) {
|
|
||||||
pkg = browsers.get(0);
|
|
||||||
} else if (!TextUtils.isEmpty(userDefaultBrowser) && browsers.contains(userDefaultBrowser)) {
|
|
||||||
pkg = userDefaultBrowser;
|
|
||||||
} else {
|
|
||||||
for (String checkpkg : checkpkgs) {
|
|
||||||
if (browsers.contains(checkpkg)) {
|
|
||||||
pkg = checkpkg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pkg == null && !browsers.isEmpty()) {
|
|
||||||
pkg = browsers.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pkg != null && customTabIntent != null) {
|
|
||||||
customTabIntent.setPackage(pkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Request storage access. The user needs to press "Select storage" at the correct storage.
|
|
||||||
* @param activity The activity which will receive the result from startActivityForResult
|
|
||||||
*/
|
|
||||||
public void requestStorageAccessFramework(final Activity... activity) {
|
|
||||||
Activity a = greedyGetActivity(activity);
|
|
||||||
if (a != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
||||||
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
|
||||||
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
|
|
||||||
);
|
|
||||||
a.startActivityForResult(intent, REQUEST_SAF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get storage access framework tree uri. The user must have granted access via {@link #requestStorageAccessFramework(Activity...)}
|
|
||||||
*
|
|
||||||
* @return Uri or null if not granted yet
|
|
||||||
*/
|
|
||||||
public Uri getStorageAccessFrameworkTreeUri() {
|
|
||||||
String treeStr = PreferenceManager.getDefaultSharedPreferences(_context).getString(PREF_KEY__SAF_TREE_URI, null);
|
|
||||||
if (!TextUtils.isEmpty(treeStr)) {
|
|
||||||
try {
|
|
||||||
return Uri.parse(treeStr);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get mounted storage folder root (by tree uri). The user must have granted access via {@link #requestStorageAccessFramework(Activity...)}
|
|
||||||
*
|
|
||||||
* @return File or null if SD not mounted
|
|
||||||
*/
|
|
||||||
public File getStorageAccessFolder() {
|
|
||||||
Uri safUri = getStorageAccessFrameworkTreeUri();
|
|
||||||
if (safUri != null) {
|
|
||||||
String safUriStr = safUri.toString();
|
|
||||||
ContextUtils cu = new ContextUtils(_context);
|
|
||||||
for (Pair<File, String> storage : cu.getStorages(false, true)) {
|
|
||||||
@SuppressWarnings("ConstantConditions") String storageFolderName = storage.first.getName();
|
|
||||||
if (safUriStr.contains(storageFolderName)) {
|
|
||||||
return storage.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cu.freeContextRef();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether or not a file is under a storage access folder (external storage / SD)
|
|
||||||
*
|
|
||||||
* @param file The file object (file/folder)
|
|
||||||
* @return Wether or not the file is under storage access folder
|
|
||||||
*/
|
|
||||||
public boolean isUnderStorageAccessFolder(final File file) {
|
|
||||||
if (file != null) {
|
|
||||||
// When file writeable as is, it's the fastest way to learn SAF isn't required
|
|
||||||
if (file.canWrite()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ContextUtils cu = new ContextUtils(_context);
|
|
||||||
for (Pair<File, String> storage : cu.getStorages(false, true)) {
|
|
||||||
if (file.getAbsolutePath().startsWith(storage.first.getAbsolutePath())) {
|
|
||||||
cu.freeContextRef();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cu.freeContextRef();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Greedy extract Activity from parameter or convert context if it's a activity
|
|
||||||
*/
|
|
||||||
private Activity greedyGetActivity(final Activity... activity) {
|
|
||||||
if (activity != null && activity.length != 0 && activity[0] != null) {
|
|
||||||
return activity[0];
|
|
||||||
}
|
|
||||||
if (_context instanceof Activity) {
|
|
||||||
return (Activity) _context;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether or not a file can be written.
|
|
||||||
* Requires storage access framework permission for external storage (SD)
|
|
||||||
*
|
|
||||||
* @param file The file object (file/folder)
|
|
||||||
* @param isDir Wether or not the given file parameter is a directory
|
|
||||||
* @return Wether or not the file can be written
|
|
||||||
*/
|
|
||||||
public boolean canWriteFile(final File file, final boolean isDir) {
|
|
||||||
if (file == null) {
|
|
||||||
return false;
|
|
||||||
} else if (file.getAbsolutePath().startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())
|
|
||||||
|| file.getAbsolutePath().startsWith(_context.getFilesDir().getAbsolutePath())) {
|
|
||||||
boolean s1 = isDir && file.getParentFile().canWrite();
|
|
||||||
return !isDir && file.getParentFile() != null ? file.getParentFile().canWrite() : file.canWrite();
|
|
||||||
} else {
|
|
||||||
DocumentFile dof = getDocumentFile(file, isDir);
|
|
||||||
return dof != null && dof.canWrite();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a {@link DocumentFile} object out of a normal java {@link File}.
|
|
||||||
* When used on a external storage (SD), use {@link #requestStorageAccessFramework(Activity...)}
|
|
||||||
* first to get access. Otherwise this will fail.
|
|
||||||
*
|
|
||||||
* @param file The file/folder to convert
|
|
||||||
* @param isDir Wether or not file is a directory. For non-existing (to be created) files this info is not known hence required.
|
|
||||||
* @return A {@link DocumentFile} object or null if file cannot be converted
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("RegExpRedundantEscape")
|
|
||||||
public DocumentFile getDocumentFile(final File file, final boolean isDir) {
|
|
||||||
// On older versions use fromFile
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
|
|
||||||
return DocumentFile.fromFile(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get ContextUtils to find storageRootFolder
|
|
||||||
ContextUtils cu = new ContextUtils(_context);
|
|
||||||
File baseFolderFile = cu.getStorageRootFolder(file);
|
|
||||||
cu.freeContextRef();
|
|
||||||
|
|
||||||
String baseFolder = baseFolderFile == null ? null : baseFolderFile.getAbsolutePath();
|
|
||||||
boolean originalDirectory = false;
|
|
||||||
if (baseFolder == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String relPath = null;
|
|
||||||
try {
|
|
||||||
String fullPath = file.getCanonicalPath();
|
|
||||||
if (!baseFolder.equals(fullPath)) {
|
|
||||||
relPath = fullPath.substring(baseFolder.length() + 1);
|
|
||||||
} else {
|
|
||||||
originalDirectory = true;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
originalDirectory = true;
|
|
||||||
}
|
|
||||||
Uri treeUri;
|
|
||||||
if ((treeUri = getStorageAccessFrameworkTreeUri()) == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
DocumentFile dof = DocumentFile.fromTreeUri(_context, treeUri);
|
|
||||||
if (originalDirectory) {
|
|
||||||
return dof;
|
|
||||||
}
|
|
||||||
String[] parts = relPath.split("\\/");
|
|
||||||
for (int i = 0; i < parts.length; i++) {
|
|
||||||
DocumentFile nextDof = dof.findFile(parts[i]);
|
|
||||||
if (nextDof == null) {
|
|
||||||
try {
|
|
||||||
nextDof = ((i < parts.length - 1) || isDir) ? dof.createDirectory(parts[i]) : dof.createFile("image", parts[i]);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
nextDof = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dof = nextDof;
|
|
||||||
}
|
|
||||||
return dof;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showMountSdDialog(@StringRes final int title, @StringRes final int description, @DrawableRes final int mountDescriptionGraphic, final Activity... activityOrNull) {
|
|
||||||
Activity activity = greedyGetActivity(activityOrNull);
|
|
||||||
if (activity == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Image viewer
|
|
||||||
ImageView imv = new ImageView(activity);
|
|
||||||
imv.setImageResource(mountDescriptionGraphic);
|
|
||||||
imv.setAdjustViewBounds(true);
|
|
||||||
|
|
||||||
AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
|
|
||||||
dialog.setView(imv);
|
|
||||||
dialog.setTitle(title);
|
|
||||||
dialog.setMessage(_context.getString(description) + "\n\n");
|
|
||||||
dialog.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
dialog.setPositiveButton(android.R.string.yes, (dialogInterface, i) -> requestStorageAccessFramework(activity));
|
|
||||||
AlertDialog dialogi = dialog.create();
|
|
||||||
dialogi.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"ResultOfMethodCallIgnored", "StatementWithEmptyBody"})
|
|
||||||
public void writeFile(final File file, final boolean isDirectory, final Callback.a2<Boolean, FileOutputStream> writeFileCallback) {
|
|
||||||
try {
|
|
||||||
FileOutputStream fileOutputStream = null;
|
|
||||||
ParcelFileDescriptor pfd = null;
|
|
||||||
final boolean existingEmptyFile = file.canWrite() && file.length() < MIN_OVERWRITE_LENGTH;
|
|
||||||
final boolean nonExistingCreatableFile = !file.exists() && file.getParentFile().canWrite();
|
|
||||||
if (existingEmptyFile || nonExistingCreatableFile) {
|
|
||||||
if (isDirectory) {
|
|
||||||
file.mkdirs();
|
|
||||||
} else {
|
|
||||||
fileOutputStream = new FileOutputStream(file);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DocumentFile dof = getDocumentFile(file, isDirectory);
|
|
||||||
if (dof != null && dof.getUri() != null && dof.canWrite()) {
|
|
||||||
if (isDirectory) {
|
|
||||||
// Nothing to do
|
|
||||||
} else {
|
|
||||||
pfd = _context.getContentResolver().openFileDescriptor(dof.getUri(), "rwt");
|
|
||||||
fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (writeFileCallback != null) {
|
|
||||||
writeFileCallback.callback(fileOutputStream != null || (isDirectory && file.exists()), fileOutputStream);
|
|
||||||
}
|
|
||||||
if (fileOutputStream != null) {
|
|
||||||
try {
|
|
||||||
fileOutputStream.close();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pfd != null) {
|
|
||||||
pfd.close();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call telephone number.
|
|
||||||
* Non direct call, opens up the dialer and pre-sets the telephone number. User needs to press manually.
|
|
||||||
* Direct call requires M permission granted, also add permissions to manifest:
|
|
||||||
* <uses-permission android:name="android.permission.CALL_PHONE" />
|
|
||||||
*
|
|
||||||
* @param telNo The telephone number to call
|
|
||||||
* @param directCall Direct call number if possible
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
|
||||||
public void callTelephoneNumber(final String telNo, final boolean... directCall) {
|
|
||||||
Activity activity = greedyGetActivity();
|
|
||||||
if (activity == null) {
|
|
||||||
throw new RuntimeException("Error: ShareUtil::callTelephoneNumber needs to be contstructed with activity context");
|
|
||||||
}
|
|
||||||
boolean ldirectCall = (directCall != null && directCall.length > 0) ? directCall[0] : true;
|
|
||||||
|
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 23 && ldirectCall && activity != null) {
|
|
||||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CALL_PHONE}, 4001);
|
|
||||||
ldirectCall = false;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
Intent callIntent = new Intent(Intent.ACTION_CALL);
|
|
||||||
callIntent.setData(Uri.parse("tel:" + telNo));
|
|
||||||
activity.startActivity(callIntent);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
ldirectCall = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Show dialer up with telephone number pre-inserted
|
|
||||||
if (!ldirectCall) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", telNo, null));
|
|
||||||
activity.startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.7 KiB |
|
@ -1,5 +0,0 @@
|
||||||
<vector android:height="24dp" android:viewportHeight="48"
|
|
||||||
android:viewportWidth="48" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<path android:fillColor="#FF000000"
|
|
||||||
android:pathData="M19.0447,29.8394 L32.0088,23.143 19.0447,16.3663ZM24,6.7503c10.0981,0 16.7945,0.4821 16.7945,0.4821 0.9375,0.1071 3,0.1071 4.8214,2.0357 0,0 1.4732,1.4464 1.9018,4.7678 0.5089,3.8839 0.4821,7.7678 0.4821,7.7678v3.6428c0,0 0.0268,3.8839 -0.4821,7.7678 -0.4286,3.2946 -1.9018,4.7678 -1.9018,4.7678 -1.8214,1.9018 -3.8839,1.9018 -4.8214,2.0089C40.7945,39.9911 34.0981,40.5 24,40.5 11.518,40.3929 7.6877,40.0179 7.6877,40.0179 6.6162,39.8304 4.2056,39.8839 2.3841,37.9822c0,0 -1.4732,-1.4732 -1.9018,-4.7678C-0.0265,29.3305 0.0002,25.4466 0.0002,25.4466v-3.6428c0,0 -0.0268,-3.8839 0.4821,-7.7678C0.9109,10.7146 2.3841,9.2682 2.3841,9.2682 4.2056,7.3396 6.268,7.3396 7.2055,7.2325c0,0 6.6964,-0.4821 16.7945,-0.4821z" android:strokeWidth="0.02678544"/>
|
|
||||||
</vector>
|
|
|
@ -5,16 +5,11 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context="com.github.dfa.diaspora_android.activity.MainActivity">
|
tools:context="com.github.dfa.diaspora_android.activity.MainActivity">
|
||||||
|
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
|
||||||
android:id="@+id/swipe"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<com.github.dfa.diaspora_android.web.ContextMenuWebView
|
<com.github.dfa.diaspora_android.web.ContextMenuWebView
|
||||||
android:id="@+id/webView"
|
android:id="@+id/webView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||||
|
@ -23,4 +18,4 @@
|
||||||
android:indeterminate="false"
|
android:indeterminate="false"
|
||||||
android:progressDrawable="@drawable/progressbar" />
|
android:progressDrawable="@drawable/progressbar" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -1,5 +1,5 @@
|
||||||
* Gregor Santner (gsantner)
|
* Gregor Santner (gsantner)
|
||||||
~° https://github.com/gsantner
|
~° http://gsantner.net
|
||||||
|
|
||||||
* Paul Schaub (vanitasvitae)
|
* Paul Schaub (vanitasvitae)
|
||||||
~° https://github.com/vanitasvitae
|
~° https://github.com/vanitasvitae
|
||||||
|
|
|
@ -1,157 +1,25 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">Maak navigasie balk oop</string>
|
|
||||||
<string name="close_navdrawer">Sluit navigasie balk</string>
|
|
||||||
<string name="reload">Herlaai</string>
|
|
||||||
<string name="close">Sluit</string>
|
|
||||||
<string name="cancel">Kanselleer</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Instellings</string>
|
|
||||||
<string name="notifications">Kennisgewings</string>
|
|
||||||
<string name="conversations">Gesprekke</string>
|
|
||||||
<string name="stream">Stroom</string>
|
|
||||||
<string name="profile">Profiel</string>
|
|
||||||
<string name="aspects">Aspekte</string>
|
|
||||||
<string name="activities">Aktiwiteite</string>
|
|
||||||
<string name="liked">Hou van</string>
|
|
||||||
<string name="commented">Opgemerk</string>
|
|
||||||
<string name="mentions">Aantal keer genoem</string>
|
|
||||||
<string name="public_">Publiek</string>
|
|
||||||
<string name="search">Soek</string>
|
|
||||||
<string name="contacts">Kontakte</string>
|
|
||||||
<string name="changelog">Verandering-log</string>
|
|
||||||
<string name="statistics">Statistiek</string>
|
|
||||||
<!-- Notifications dropdown menu -->
|
<!-- Notifications dropdown menu -->
|
||||||
<string name="all_notifications">Alle kennisgewings</string>
|
|
||||||
<string name="also_commented">Ook Opgemerk</string>
|
|
||||||
<string name="comment_on_post">Lewer kommentaar op hierdie plasing</string>
|
|
||||||
<string name="deleteme_____1">Hou van</string>
|
|
||||||
<string name="mentioned">Aantal keer genoem</string>
|
|
||||||
<string name="reshared">Herdeel</string>
|
|
||||||
<string name="started_sharing">Begin deel</string>
|
|
||||||
<!-- Pod Activity -->
|
<!-- Pod Activity -->
|
||||||
<string name="could_not_retrieve_list_of_pods__appspecific">Fout: Kon nie lys van pods verkry nie!</string>
|
|
||||||
<string name="confirmation">Bevestiging</string>
|
|
||||||
<string name="do_you_want_to_exit">Wil jy uitgaan?</string>
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
||||||
<string name="more">Meer</string>
|
|
||||||
<string name="help_license">Omtrent | Hulp</string>
|
|
||||||
<string name="followed_tags">Gevolgde merkers</string>
|
|
||||||
<string name="public_activities">Publieke aktiwiteite</string>
|
|
||||||
<string name="reports">Verslae</string>
|
|
||||||
<string name="share_link_as_text">Deel skakel as teks</string>
|
|
||||||
<string name="share_screenshot_of_webpage">Deel vriesbeeld van webbladsy</string>
|
|
||||||
<string name="take_screenshot_of_webpage">Neem vriesbeeld van webbladsy</string>
|
|
||||||
<string name="saving_image_to">Stoor beeld na</string>
|
|
||||||
<string name="saving_screenshot_as">Stoor vriesbeeld as:</string>
|
|
||||||
<string name="link_adress_copied">Skakel adres gekopieer…</string>
|
|
||||||
<string name="new_post">Nuwe Plasing</string>
|
|
||||||
<string name="go_to_top">Gaan tot bo</string>
|
|
||||||
<string name="search_by_tags_or_persons__appspecific">Soek met merkers of persone</string>
|
|
||||||
<string name="exit_app">Verlaat toep</string>
|
|
||||||
<string name="toggle_mobile_desktop_view">Wissel Mobiele/Monitor oogpunt</string>
|
|
||||||
<string name="share_dotdotdot">Deel…</string>
|
|
||||||
<string name="by_tags">met merkers</string>
|
|
||||||
<string name="by_people">met mense</string>
|
|
||||||
<string name="please_add_a_name">Voer asseblief \'n naam in</string>
|
|
||||||
<string name="share_link_address">Deel skakel adres</string>
|
|
||||||
<string name="save_image">Stoor beeld</string>
|
|
||||||
<string name="share_image">Deel beeld</string>
|
|
||||||
<string name="open_in_external_browser">Maak in eksterne webleser oop…</string>
|
|
||||||
<string name="copy_link_adress_to_clipboard">Kopieer skakel adres na knipbord</string>
|
|
||||||
<string name="copy_image_address_to_clipboard">Kopieer beeld adres na knipbord</string>
|
|
||||||
<!-- More from MainActivity -->
|
<!-- More from MainActivity -->
|
||||||
<string name="unable_to_load_image">Kon nie beeld laai nie</string>
|
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
<string name="permission_denied">Toestemming geweier.</string>
|
|
||||||
<string name="pod_name">Pod naam</string>
|
|
||||||
<string name="protocol">Protokol</string>
|
|
||||||
<string name="pod_address">Pod adres</string>
|
|
||||||
<string name="missing_value">Vermiste waarde</string>
|
|
||||||
<string name="hide_statusbar">Versteek status balk</string>
|
|
||||||
<string name="show_title">Wys titel</string>
|
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<!-- Category Titles -->
|
<!-- Category Titles -->
|
||||||
<string name="appearance">Voorkoms</string>
|
|
||||||
<string name="network">Netwerk</string>
|
|
||||||
<string name="pod_settings__appspecfic">Pod verstellings</string>
|
|
||||||
<!-- Visuals -->
|
<!-- Visuals -->
|
||||||
<!-- Navigiation Slider -->
|
<!-- Navigiation Slider -->
|
||||||
<string name="user">Gebruiker</string>
|
|
||||||
<string name="general">Algemeen</string>
|
|
||||||
<string name="admin">Admin</string>
|
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<string name="theme_and_colors">Tema en kleure</string>
|
|
||||||
<string name="primary_colors">Primêre kleur</string>
|
|
||||||
<string name="colors_of_toolbars">Kleur van die nutsbalke</string>
|
|
||||||
<string name="accent_color">Kontras kleur</string>
|
|
||||||
<string name="color_of_progressbar">Kleur van die vorderingsbalk</string>
|
|
||||||
<string name="amoled_mode">AMOLED modus</string>
|
|
||||||
<!-- Notifications dropdown -->
|
<!-- Notifications dropdown -->
|
||||||
<string name="extended_notifications">Uitgebreide Kennisgewings</string>
|
|
||||||
<string name="language">Taal</string>
|
|
||||||
<!-- Font size -->
|
<!-- Font size -->
|
||||||
<string name="font_size">Fontgrootte</string>
|
|
||||||
<string name="normal">Normaal</string>
|
|
||||||
<string name="large">Groot</string>
|
|
||||||
<string name="huge">Masief</string>
|
|
||||||
<!-- Load images -->
|
<!-- Load images -->
|
||||||
<string name="load_images">Laai beelde</string>
|
|
||||||
<!-- Screen rotation -->
|
<!-- Screen rotation -->
|
||||||
<string name="screen_rotation">Skerm Rotasie</string>
|
|
||||||
<string name="control_screen_rotation">Beheer outomatiese skermrotasie</string>
|
|
||||||
<string name="default_">Verstek</string>
|
|
||||||
<string name="portrait">Portret</string>
|
|
||||||
<string name="landscape">Landskap</string>
|
|
||||||
<!-- Proxy -->
|
<!-- Proxy -->
|
||||||
<string name="load_tor_preset">Laai Tor voorkeure</string>
|
|
||||||
<string name="proxy">Volmag</string>
|
|
||||||
<string name="host">Gasheer</string>
|
|
||||||
<string name="port">Poort</string>
|
|
||||||
<string name="app_needs_restart_to_disable_proxy_usage">Toep moet herlaai om volmag te deaktiveer</string>
|
|
||||||
<string name="orbot_proxy_preset_loaded">Orbot volmag voorkeure gelaai</string>
|
|
||||||
<!-- Chrome custom tabs -->
|
<!-- Chrome custom tabs -->
|
||||||
<!-- Diaspora Settings -->
|
<!-- Diaspora Settings -->
|
||||||
<string name="personal_settings">Persoonlike instellings</string>
|
|
||||||
<string name="manage_hashtags">Bestuur Hutsmerke</string>
|
|
||||||
<string name="unfollow_already_followed_hashtags__appspecific">Onvolg Hutsmerke</string>
|
|
||||||
<string name="change_account">Verander rekening</string>
|
|
||||||
<string name="clear_cache">Vee Buffer</string>
|
|
||||||
<string name="clear_webview_cache">Vee WebBuffer skoon</string>
|
|
||||||
<!-- More -->
|
<!-- More -->
|
||||||
<string name="miscellaneous">Diverse</string>
|
|
||||||
<string name="full_reset">Volle herstel</string>
|
|
||||||
<string name="block_advertisments">Blok advertensies</string>
|
|
||||||
<string name="about">Omtrent</string>
|
|
||||||
<string name="license">Lisensie</string>
|
|
||||||
<string name="debugging">Ontfouting</string>
|
|
||||||
<string name="application">Toepassing</string>
|
|
||||||
<string name="device">Toestel</string>
|
|
||||||
<string name="diaspora_pod__appspecific">diaspora * Pod</string>
|
|
||||||
<string name="app_version_with_arg">Tope weergawe: %1$s</string>
|
|
||||||
<string name="android_version_witharg">Android Weergawe%1$s</string>
|
|
||||||
<string name="device_name_witharg">Toestel naam%1$s</string>
|
|
||||||
<string name="code_name_witharg">Kodenaam: %1$s</string>
|
|
||||||
<string name="pod_profile_name_witharg__appspecific">Pod profiel naam: %1$s</string>
|
|
||||||
<string name="pod_domain_witharg__appspecific">Pod domein: %1$s</string>
|
|
||||||
<string name="get_the_source">Verkry die bron</string>
|
|
||||||
<string name="translate_the_app">Vertaal hierdie Toep!</string>
|
|
||||||
<string name="app_not_available_in_your_lang_translate_with_stringlate">Die toepassing is nie in jou taal beskikbaar? Jy kan dit verander! Hoekom help jy ons nie met die vertaling nie? Ons gebruik Stringlate om enigiemand te help om toepassing te vertaal.</string>
|
|
||||||
<string name="let_me_translate">Laat ek vertaal</string>
|
|
||||||
<string name="give_feedback">Gee terugvoer!</string>
|
|
||||||
<string name="dandelion_still_in_development__appspecific">dandelion * is nog in ontwikkeling, so as jy voorstelle of enige soort terugvoer het, gebruik asseblief ons probleem volger laat ons weet!</string>
|
|
||||||
<string name="report_bugs">Raporteer foute</string>
|
|
||||||
<string name="share_the_app">Deel die toep</string>
|
|
||||||
<string name="hey_checkout_dandelion_tag__appspecific">Haai! Loer na #dandelion! %1$s</string>
|
|
||||||
<!-- License & help (large amount of text) -->
|
<!-- License & help (large amount of text) -->
|
||||||
<string name="maintainers">Handhawers</string>
|
|
||||||
<string name="thank_you_witharg">%1$s<br><br>baie dankie!</string>
|
|
||||||
<string name="gnu_gplv3_license">GNU GPLv3+ Lisensie</string>
|
|
||||||
<string name="show_third_party_licenses">Derdeparty biblioteke</string>
|
|
||||||
<string name="tell_me_more">Vertel my meer</string>
|
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Bemagtig om Youtube links oop te maak in eksterne Toeps</string>
|
|
||||||
<string name="youtube_links">Youtube links</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Verander die tema van jou rekening</string>
|
|
||||||
<string name="pull_to_refresh">Trek om te verfris</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,41 +1,25 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">إعدادات</string>
|
|
||||||
<string name="search">بحث</string>
|
|
||||||
<string name="changelog">سِجل التغييرات</string>
|
|
||||||
<!-- Notifications dropdown menu -->
|
<!-- Notifications dropdown menu -->
|
||||||
<!-- Pod Activity -->
|
<!-- Pod Activity -->
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
||||||
<string name="more">المزيد</string>
|
|
||||||
<string name="share_dotdotdot">مشاركة</string>
|
|
||||||
<!-- More from MainActivity -->
|
<!-- More from MainActivity -->
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
<string name="hide_statusbar">اخفاء شريط الاشعارات</string>
|
|
||||||
<string name="show_title">إظهار العنوان</string>
|
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<!-- Category Titles -->
|
<!-- Category Titles -->
|
||||||
<string name="appearance">المظهر</string>
|
|
||||||
<!-- Visuals -->
|
<!-- Visuals -->
|
||||||
<!-- Navigiation Slider -->
|
<!-- Navigiation Slider -->
|
||||||
<string name="general">عام</string>
|
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<!-- Notifications dropdown -->
|
<!-- Notifications dropdown -->
|
||||||
<string name="language_change_restart_description">تغيير لغة التطبيق. اعد فتح التطبيق لتفعيل التغيير</string>
|
|
||||||
<string name="language">اللّغة</string>
|
|
||||||
<!-- Font size -->
|
<!-- Font size -->
|
||||||
<!-- Load images -->
|
<!-- Load images -->
|
||||||
<!-- Screen rotation -->
|
<!-- Screen rotation -->
|
||||||
<string name="default_">افتراضي</string>
|
|
||||||
<!-- Proxy -->
|
<!-- Proxy -->
|
||||||
<!-- Chrome custom tabs -->
|
<!-- Chrome custom tabs -->
|
||||||
<!-- Diaspora Settings -->
|
<!-- Diaspora Settings -->
|
||||||
<string name="clear_cache">مسح ذاكرة التخزين المؤقت</string>
|
|
||||||
<!-- More -->
|
<!-- More -->
|
||||||
<string name="miscellaneous">أخرى</string>
|
|
||||||
<string name="about">عن التطبيق</string>
|
|
||||||
<string name="license">ترخيص</string>
|
|
||||||
<!-- License & help (large amount of text) -->
|
<!-- License & help (large amount of text) -->
|
||||||
<string name="contributors">المساهمون</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,41 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<string name="open_navdrawer">Otvori navigacijsku ladicu</string>
|
|
||||||
<string name="close_navdrawer">Zatvorite navigacijsku ladicu</string>
|
|
||||||
<string name="close">Zatvori</string>
|
|
||||||
<string name="cancel">Otkaži</string>
|
|
||||||
<!-- Common Words -->
|
|
||||||
<string name="settings">Podešavanja</string>
|
|
||||||
<string name="search">Traži</string>
|
|
||||||
<string name="changelog">Popis izmjena</string>
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<string name="more">Više</string>
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<string name="hide_statusbar">Sakrij statusnu traku</string>
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<string name="appearance">Izgled</string>
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<string name="general">Opće</string>
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<string name="language_change_restart_description">Promijeni jezik programa. Iznova pokrenite program da aktivirate promjenu</string>
|
|
||||||
<string name="language">Jezik</string>
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<string name="default_">Osnovni</string>
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<string name="miscellaneous">Razno</string>
|
|
||||||
<string name="about">O programu</string>
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
<string name="contributors">Saradnici</string>
|
|
||||||
</resources>
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">Obre el calaix de navegació</string>
|
<string name="open_navdrawer">Obre el calaix de navegació</string>
|
||||||
<string name="close_navdrawer">Tanca el calaix de navegació</string>
|
<string name="close_navdrawer">Tanca el calaix de navegació</string>
|
||||||
<string name="reload">Recarrega</string>
|
<string name="reload">Recarrega</string>
|
||||||
<string name="close">Tanca</string>
|
|
||||||
<string name="cancel">Cancel·la</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Configuració</string>
|
<string name="settings">Configuració</string>
|
||||||
<string name="notifications">Notificacions</string>
|
<string name="notifications">Notificacions</string>
|
||||||
|
@ -121,7 +120,7 @@ Aneu a: Configuració del sistema - Aplicacions - dandelion*. A la secció de pe
|
||||||
<string name="load_images">Carrega imatges</string>
|
<string name="load_images">Carrega imatges</string>
|
||||||
<string name="toggle_image_loading_to_save_mobile_data">Commuta la càrrega d\'imatges a p. ex. estalvia dades mòbils</string>
|
<string name="toggle_image_loading_to_save_mobile_data">Commuta la càrrega d\'imatges a p. ex. estalvia dades mòbils</string>
|
||||||
<!-- Screen rotation -->
|
<!-- Screen rotation -->
|
||||||
<string name="screen_rotation">Rotació de pantalla</string>
|
<string name="screen_rotation">Rotació de la pantalla</string>
|
||||||
<string name="control_screen_rotation">Control automàtic de la rotació de la pantalla</string>
|
<string name="control_screen_rotation">Control automàtic de la rotació de la pantalla</string>
|
||||||
<string name="default_">Per defecte</string>
|
<string name="default_">Per defecte</string>
|
||||||
<string name="sensor_ignore_system_settings">Sensor\n(ignora la configuració del sistema)</string>
|
<string name="sensor_ignore_system_settings">Sensor\n(ignora la configuració del sistema)</string>
|
||||||
|
@ -201,9 +200,4 @@ diaspora*. Si voleu contribuir, endavant! Actualment som un equip molt petit, de
|
||||||
<string name="the_following_libraries_are_used">S\'utilitzen les següents biblioteques:</string>
|
<string name="the_following_libraries_are_used">S\'utilitzen les següents biblioteques:</string>
|
||||||
<string name="inspiration_from_leafpic__appspecific">Prenem alguna inspiració i codi de LeafPic. Aneu a comprovar-ho, també és programari gratuït!</string>
|
<string name="inspiration_from_leafpic__appspecific">Prenem alguna inspiració i codi de LeafPic. Aneu a comprovar-ho, també és programari gratuït!</string>
|
||||||
<string name="tell_me_more">Expliqueu-me més</string>
|
<string name="tell_me_more">Expliqueu-me més</string>
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Activeu-ho per obrir enllaços de Youtube en aplicacions externes</string>
|
|
||||||
<string name="youtube_links">Enllaços de YouTube</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Canvia el tema del vostre compte</string>
|
|
||||||
<string name="pull_to_refresh">Feu lliscar per actualitzar</string>
|
|
||||||
<string name="pulling_down_on_top_of_page_to_refresh">S\'està lliscant cap avall a la part superior de la pàgina per actualitzar.\nCal que reinicieu l\'aplicació perquè els canvis tinguin efecte.</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">Otevøít navigaèní panel</string>
|
<string name="open_navdrawer">Otevøít navigaèní panel</string>
|
||||||
<string name="close_navdrawer">Zavøít navigaèní panel</string>
|
<string name="close_navdrawer">Zavøít navigaèní panel</string>
|
||||||
<string name="reload">Aktualizovat</string>
|
<string name="reload">Aktualizovat</string>
|
||||||
<string name="close">Konec</string>
|
|
||||||
<string name="cancel">Rakovina</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Nastavení</string>
|
<string name="settings">Nastavení</string>
|
||||||
<string name="notifications">Oznámení</string>
|
<string name="notifications">Oznámení</string>
|
||||||
|
@ -21,7 +20,6 @@
|
||||||
<string name="search">Hledat</string>
|
<string name="search">Hledat</string>
|
||||||
<string name="contacts">Kontakty</string>
|
<string name="contacts">Kontakty</string>
|
||||||
<string name="changelog">Seznam změn</string>
|
<string name="changelog">Seznam změn</string>
|
||||||
<string name="statistics">Statistika</string>
|
|
||||||
<!-- Notifications dropdown menu -->
|
<!-- Notifications dropdown menu -->
|
||||||
<string name="all_notifications">Všechna oznámení</string>
|
<string name="all_notifications">Všechna oznámení</string>
|
||||||
<string name="also_commented">Také komentováno</string>
|
<string name="also_commented">Také komentováno</string>
|
||||||
|
@ -31,37 +29,21 @@
|
||||||
<string name="reshared">Sdílen</string>
|
<string name="reshared">Sdílen</string>
|
||||||
<string name="started_sharing">Začalo sdílení</string>
|
<string name="started_sharing">Začalo sdílení</string>
|
||||||
<!-- Pod Activity -->
|
<!-- Pod Activity -->
|
||||||
<string name="could_not_retrieve_list_of_pods__appspecific">Error: Nemohl získat seznam podů!</string>
|
|
||||||
<string name="sorry_need_to_be_connected_to_internet">Omlouvám se, musíte být připojeni k internetu, abyste mohli pokračovat dál</string>
|
|
||||||
<string name="confirmation">Potvrzení</string>
|
<string name="confirmation">Potvrzení</string>
|
||||||
<string name="do_you_want_to_exit">Chceš opustit aplikaci?</string>
|
<string name="do_you_want_to_exit">Chceš opustit aplikaci?</string>
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
||||||
<string name="more">Více</string>
|
<string name="more">Více</string>
|
||||||
<string name="help_license">O aplikaci | Pomoc</string>
|
<string name="help_license">O aplikaci | Pomoc</string>
|
||||||
<string name="followed_tags">Zlaté rány</string>
|
|
||||||
<string name="public_activities">Veřejné aktivity</string>
|
<string name="public_activities">Veřejné aktivity</string>
|
||||||
<string name="reports">Nahlášení</string>
|
<string name="reports">Nahlášení</string>
|
||||||
<string name="share_link_as_text">Sdílejte odkaz jako text</string>
|
|
||||||
<string name="share_screenshot_of_webpage">Šablony obrázku webových stránek</string>
|
|
||||||
<string name="take_screenshot_of_webpage">Podívejte se na snímek webové stránky</string>
|
|
||||||
<string name="saving_image_to">Uložit obrázek</string>
|
|
||||||
<string name="saving_screenshot_as">Uložit snímky jako:</string>
|
|
||||||
<string name="link_adress_copied">Zapnutá adresa …</string>
|
|
||||||
<string name="new_post">Nový příspěvek</string>
|
<string name="new_post">Nový příspěvek</string>
|
||||||
<string name="go_to_top">Jít nahoru</string>
|
<string name="go_to_top">Jít nahoru</string>
|
||||||
<string name="search_by_tags_or_persons__appspecific">Hledat štítky nebo osoby</string>
|
|
||||||
<string name="exit_app">Ukončit aplikaci</string>
|
<string name="exit_app">Ukončit aplikaci</string>
|
||||||
<string name="toggle_mobile_desktop_view">Pohled na pracovní plochu</string>
|
|
||||||
<string name="share_dotdotdot">Sdílet…</string>
|
<string name="share_dotdotdot">Sdílet…</string>
|
||||||
<string name="by_tags">tagy</string>
|
|
||||||
<string name="by_people">lidmi</string>
|
|
||||||
<string name="please_add_a_name">Prosím přidejte jméno</string>
|
|
||||||
<string name="share_link_address">Sdílejte adresu odkazu</string>
|
|
||||||
<string name="save_image">Uložit obrázek</string>
|
<string name="save_image">Uložit obrázek</string>
|
||||||
<string name="share_image">Sdílet obrázek</string>
|
<string name="share_image">Sdílet obrázek</string>
|
||||||
<string name="open_in_external_browser">Otevřít v externím prohlížeči…</string>
|
<string name="open_in_external_browser">Otevřít v externím prohlížeči…</string>
|
||||||
<string name="copy_link_adress_to_clipboard">Zkopírovat link do schránky</string>
|
<string name="copy_link_adress_to_clipboard">Zkopírovat link do schránky</string>
|
||||||
<string name="copy_image_address_to_clipboard">Kopírovat adresu obrázku do schránky</string>
|
|
||||||
<!-- More from MainActivity -->
|
<!-- More from MainActivity -->
|
||||||
<string name="unable_to_load_image">Nemohl být načten obrázek</string>
|
<string name="unable_to_load_image">Nemohl být načten obrázek</string>
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
|
@ -74,11 +56,7 @@
|
||||||
<string name="pod_address">Adresa Podu</string>
|
<string name="pod_address">Adresa Podu</string>
|
||||||
<string name="missing_value">Chybějící hodnota</string>
|
<string name="missing_value">Chybějící hodnota</string>
|
||||||
<string name="jump_to_last_visited_page_in_stream__appspecific">Zavolat poslední navštívenou stránku ve streamu?</string>
|
<string name="jump_to_last_visited_page_in_stream__appspecific">Zavolat poslední navštívenou stránku ve streamu?</string>
|
||||||
<string name="hide_statusbar_in_mainview">Hide bar at the main view at the view.</string>
|
|
||||||
<string name="hide_statusbar">Schovat statusbar</string>
|
<string name="hide_statusbar">Schovat statusbar</string>
|
||||||
<string name="show_title_in_main_view">Zobrazit titul v hlavním pohledu</string>
|
|
||||||
<string name="show_title">Zobrazit titul</string>
|
|
||||||
<string name="launcher_shortcut">Launcher shortcut</string>
|
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<string name="top_toolbar_loads_stream__appsp">Horní nástrojová lišta načítá stream</string>
|
<string name="top_toolbar_loads_stream__appsp">Horní nástrojová lišta načítá stream</string>
|
||||||
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Pro otevření streamu klikni na práznou plochu v horní nástrojové liště</string>
|
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Pro otevření streamu klikni na práznou plochu v horní nástrojové liště</string>
|
||||||
|
@ -89,20 +67,14 @@
|
||||||
<string name="operability">Obsluha</string>
|
<string name="operability">Obsluha</string>
|
||||||
<!-- Visuals -->
|
<!-- Visuals -->
|
||||||
<!-- Navigiation Slider -->
|
<!-- Navigiation Slider -->
|
||||||
<string name="navigation_drawer">Navigační šprýmař</string>
|
|
||||||
<string name="control_visibility_of_entries_nav_drawer">Ovládejte viditelnost položek v navigačním šuplíku</string>
|
|
||||||
<string name="user">Uživatel</string>
|
<string name="user">Uživatel</string>
|
||||||
<string name="general">Obecné</string>
|
<string name="general">Obecné</string>
|
||||||
<string name="admin">Administrátor</string>
|
<string name="admin">Administrátor</string>
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<string name="theme_and_colors">Téma a zmatek</string>
|
|
||||||
<string name="control_which_colors_are_used_in_app">Ovládání, které barvy jsou používány v průběhu aplikace</string>
|
|
||||||
<string name="primary_colors">Primární barva</string>
|
<string name="primary_colors">Primární barva</string>
|
||||||
<string name="colors_of_toolbars">Barva nástrojové lišty</string>
|
<string name="colors_of_toolbars">Barva nástrojové lišty</string>
|
||||||
<string name="accent_color">Akcentová barva</string>
|
<string name="accent_color">Akcentová barva</string>
|
||||||
<string name="color_of_progressbar">Barva detailů</string>
|
<string name="color_of_progressbar">Barva detailů</string>
|
||||||
<string name="amoled_mode">AMOLED model</string>
|
|
||||||
<string name="amoled_mode_description__app_specific">Pro procházení barvy s AMOLED zobrazujeme příjemnou černou barvu v mnoha částech aplikace.</string>
|
|
||||||
<!-- Notifications dropdown -->
|
<!-- Notifications dropdown -->
|
||||||
<string name="extended_notifications">Rozšířené oznámení</string>
|
<string name="extended_notifications">Rozšířené oznámení</string>
|
||||||
<string name="extendend_notifications_bell_description__appspecific">Rozšiř oznámení zvonku pomocí výběrového menu, které zobrazuje kategorie oznámení</string>
|
<string name="extendend_notifications_bell_description__appspecific">Rozšiř oznámení zvonku pomocí výběrového menu, které zobrazuje kategorie oznámení</string>
|
||||||
|
@ -117,7 +89,6 @@
|
||||||
<string name="huge">Obrovské</string>
|
<string name="huge">Obrovské</string>
|
||||||
<!-- Load images -->
|
<!-- Load images -->
|
||||||
<string name="load_images">Načítej obrázky</string>
|
<string name="load_images">Načítej obrázky</string>
|
||||||
<string name="toggle_image_loading_to_save_mobile_data">Útok obrázku na např. uložte mobilní data</string>
|
|
||||||
<!-- Screen rotation -->
|
<!-- Screen rotation -->
|
||||||
<string name="screen_rotation">Rotace obrazovky</string>
|
<string name="screen_rotation">Rotace obrazovky</string>
|
||||||
<string name="control_screen_rotation">Kontroluj automatickou rotaci</string>
|
<string name="control_screen_rotation">Kontroluj automatickou rotaci</string>
|
||||||
|
@ -133,31 +104,15 @@
|
||||||
<string name="proxy_dandelion_traffic__appspecific">Veď datovou cestu dandelion*, aby se obešla brána Firewall.\nMůže být vyžadován restart. Toto nemusí fungovat na všech přístrojích.</string>
|
<string name="proxy_dandelion_traffic__appspecific">Veď datovou cestu dandelion*, aby se obešla brána Firewall.\nMůže být vyžadován restart. Toto nemusí fungovat na všech přístrojích.</string>
|
||||||
<string name="host">Host</string>
|
<string name="host">Host</string>
|
||||||
<string name="port">Port</string>
|
<string name="port">Port</string>
|
||||||
<string name="app_needs_restart_to_disable_proxy_usage">Při restartu musíte zakázat používání proxy serveru</string>
|
|
||||||
<string name="orbot_proxy_preset_loaded">načtený panel proxy</string>
|
|
||||||
<!-- Chrome custom tabs -->
|
<!-- Chrome custom tabs -->
|
||||||
<!-- Diaspora Settings -->
|
<!-- Diaspora Settings -->
|
||||||
<string name="personal_settings">Osobní nastavení</string>
|
<string name="personal_settings">Osobní nastavení</string>
|
||||||
<string name="open_diaspora_account_settings__appspecific">Otevřte nastavení účtu diaspory</string>
|
|
||||||
<string name="manage_your_contact_list">Spravte Váš seznam kontaktů</string>
|
|
||||||
<string name="manage_hashtags">Řídit Hashtagy</string>
|
|
||||||
<string name="unfollow_already_followed_hashtags__appspecific">Unfollow již následoval hashts</string>
|
|
||||||
<string name="change_account">Změna konta</string>
|
<string name="change_account">Změna konta</string>
|
||||||
<string name="loug_warning_description__appspecific">Erase local session data and switch to another diaspora* pod/účet</string>
|
|
||||||
<string name="logout_warning_description">Chcete změnit svůj účet?</string>
|
|
||||||
<string name="clear_cache">Vyprázdnit cache</string>
|
<string name="clear_cache">Vyprázdnit cache</string>
|
||||||
<string name="clear_webview_cache">Smazat cache WebView</string>
|
|
||||||
<string name="intellihide_toolbars__appspecific">Automaticky skryjí horní a dolní lišty při každém hodnocení.</string>
|
|
||||||
<string name="intellihide_toolbars">Lity rozumových nástrojů</string>
|
|
||||||
<string name="append_shared_by_notice">Konečný společný přístup</string>
|
|
||||||
<string name="append_shared_by_notice__appspecific">Přidat referenci této aplikace ke sdílenému textu: [via #dandelion]</string>
|
<string name="append_shared_by_notice__appspecific">Přidat referenci této aplikace ke sdílenému textu: [via #dandelion]</string>
|
||||||
<!-- More -->
|
<!-- More -->
|
||||||
<string name="miscellaneous">Různé</string>
|
<string name="miscellaneous">Různé</string>
|
||||||
<string name="full_reset">Celkový reset</string>
|
<string name="full_reset">Celkový reset</string>
|
||||||
<string name="wipe_settings_and_logout">Podařilo se vám smazat všechna nastavení související s aplikací a přihlásit se ze všech účtů.</string>
|
|
||||||
<string name="wipe_settings_warning__appspecific">Toto přepíše všechna změněná nastavení aplikace do výchozích hodnot a vymaže vás ze všech podů.</string>
|
|
||||||
<string name="enable_basic_adblocker_description">Uživatelné základní Adcker může být součástí např. v embedded views.</string>
|
|
||||||
<string name="block_advertisments">Blokové reklamy</string>
|
|
||||||
<string name="about">Informace</string>
|
<string name="about">Informace</string>
|
||||||
<string name="license">Licence</string>
|
<string name="license">Licence</string>
|
||||||
<string name="debugging">Debugging</string>
|
<string name="debugging">Debugging</string>
|
||||||
|
@ -178,26 +133,16 @@
|
||||||
<string name="dandelion_is_developed_as_foss__appspecific">dandelion* je svobodný software (free as in Freedom) a řídí se myšlenkami projektu diaspora*. Pokud chceš přispívat, jen do toho! Momentálně jsme velmi malý tým, takže jsme velmi vděční za jakýkoli druh pomoci!</string>
|
<string name="dandelion_is_developed_as_foss__appspecific">dandelion* je svobodný software (free as in Freedom) a řídí se myšlenkami projektu diaspora*. Pokud chceš přispívat, jen do toho! Momentálně jsme velmi malý tým, takže jsme velmi vděční za jakýkoli druh pomoci!</string>
|
||||||
<string name="get_the_source">Ke zdrojovému kódu</string>
|
<string name="get_the_source">Ke zdrojovému kódu</string>
|
||||||
<string name="translate_the_app">Přelož aplikaci!</string>
|
<string name="translate_the_app">Přelož aplikaci!</string>
|
||||||
<string name="app_not_available_in_your_lang_translate_with_stringlate">Pokud si nejste jistí, že jste se rozhodli pro něco, co potřebujete?</string>
|
|
||||||
<string name="let_me_translate">Chci překládat</string>
|
<string name="let_me_translate">Chci překládat</string>
|
||||||
<string name="give_feedback">Dej zpětnou vazbu!</string>
|
<string name="give_feedback">Dej zpětnou vazbu!</string>
|
||||||
<string name="dandelion_still_in_development__appspecific">dandelion* je stále ve vývoji, takže pokud máš jakékoli návrhy, neváhej nám zanechat zpětnou vazbu pomocí užití našeho bug trackeru!</string>
|
<string name="dandelion_still_in_development__appspecific">dandelion* je stále ve vývoji, takže pokud máš jakékoli návrhy, neváhej nám zanechat zpětnou vazbu pomocí užití našeho bug trackeru!</string>
|
||||||
<string name="report_bugs">Nahlásit chybu</string>
|
<string name="report_bugs">Nahlásit chybu</string>
|
||||||
<string name="spread_the_word">Řekni o aplikaci ostatním!</string>
|
<string name="spread_the_word">Řekni o aplikaci ostatním!</string>
|
||||||
<string name="tell_your_friends_about_diaspora__appspecific">Řekni svým přátelům a rodině o diaspora* a #dadelion! Proč nezačít blogovat o Tvých zkušenostech? Rádi o Tobě uslyšíme!</string>
|
<string name="tell_your_friends_about_diaspora__appspecific">Řekni svým přátelům a rodině o diaspora* a #dadelion! Proč nezačít blogovat o Tvých zkušenostech? Rádi o Tobě uslyšíme!</string>
|
||||||
<string name="share_the_app">Sdílejte chuť</string>
|
|
||||||
<string name="hey_checkout_dandelion_tag__appspecific">Hey! Podívejte se na #dandelion! %1$s</string>
|
|
||||||
<!-- License & help (large amount of text) -->
|
<!-- License & help (large amount of text) -->
|
||||||
<string name="maintainers">Vývojáři</string>
|
<string name="maintainers">Vývojáři</string>
|
||||||
<string name="contributors">Spolupracovníci</string>
|
<string name="contributors">Spolupracovníci</string>
|
||||||
<string name="thank_you_witharg">%1$s<br><br>Děkujeme!</string>
|
<string name="thank_you_witharg">%1$s<br><br>Děkujeme!</string>
|
||||||
<string name="gnu_gplv3_license">GNU GPLv3+ Licence</string>
|
<string name="gnu_gplv3_license">GNU GPLv3+ Licence</string>
|
||||||
<string name="show_third_party_licenses">Knihovny třetí strany</string>
|
|
||||||
<string name="the_following_libraries_are_used">Následující knihovny jsou využívány:</string>
|
|
||||||
<string name="inspiration_from_leafpic__appspecific">We took some inspiration and code from LeafPic.</string>
|
|
||||||
<string name="tell_me_more">Řekni mi více</string>
|
<string name="tell_me_more">Řekni mi více</string>
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Umožnit otevřít Youtube odkazy na externí aplikace</string>
|
|
||||||
<string name="youtube_links">Youtube odkazy</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Změňte téma vašeho účtu</string>
|
|
||||||
<string name="pull_to_refresh">Pull osvěžit</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="reload">Genindlæs</string>
|
<string name="reload">Genindlæs</string>
|
||||||
|
@ -34,16 +35,13 @@
|
||||||
<string name="copy_link_adress_to_clipboard">Kopier link-adresse til udklipsholder</string>
|
<string name="copy_link_adress_to_clipboard">Kopier link-adresse til udklipsholder</string>
|
||||||
<!-- More from MainActivity -->
|
<!-- More from MainActivity -->
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
<string name="hide_statusbar">Gem statusbar</string>
|
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<string name="top_toolbar_loads_stream__appsp">Øverste værktøjslinje indlæser strøm</string>
|
<string name="top_toolbar_loads_stream__appsp">Øverste værktøjslinje indlæser strøm</string>
|
||||||
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Klik på tom plads i den øverste værktøjslinje for at åbne strømme</string>
|
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Klik på tom plads i den øverste værktøjslinje for at åbne strømme</string>
|
||||||
<!-- Category Titles -->
|
<!-- Category Titles -->
|
||||||
<string name="appearance">Udseende</string>
|
|
||||||
<string name="network">Netværk</string>
|
<string name="network">Netværk</string>
|
||||||
<!-- Visuals -->
|
<!-- Visuals -->
|
||||||
<!-- Navigiation Slider -->
|
<!-- Navigiation Slider -->
|
||||||
<string name="general">Generelt</string>
|
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<string name="primary_colors">Primær farve</string>
|
<string name="primary_colors">Primær farve</string>
|
||||||
<string name="colors_of_toolbars">Værktøjslinjers farver</string>
|
<string name="colors_of_toolbars">Værktøjslinjers farver</string>
|
||||||
|
@ -54,7 +52,6 @@
|
||||||
<!-- Font size -->
|
<!-- Font size -->
|
||||||
<!-- Load images -->
|
<!-- Load images -->
|
||||||
<!-- Screen rotation -->
|
<!-- Screen rotation -->
|
||||||
<string name="default_">Standard</string>
|
|
||||||
<!-- Proxy -->
|
<!-- Proxy -->
|
||||||
<!-- Chrome custom tabs -->
|
<!-- Chrome custom tabs -->
|
||||||
<!-- Diaspora Settings -->
|
<!-- Diaspora Settings -->
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">NavDrawer öffnen</string>
|
<string name="open_navdrawer">NavDrawer öffnen</string>
|
||||||
<string name="close_navdrawer">NavDrawer schließen</string>
|
<string name="close_navdrawer">NavDrawer schließen</string>
|
||||||
<string name="reload">Aktualisieren</string>
|
<string name="reload">Aktualisieren</string>
|
||||||
<string name="close">Schließen</string>
|
|
||||||
<string name="cancel">Abbrechen</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Einstellungen</string>
|
<string name="settings">Einstellungen</string>
|
||||||
<string name="notifications">Benachrichtigungen</string>
|
<string name="notifications">Benachrichtigungen</string>
|
||||||
|
@ -52,7 +51,7 @@
|
||||||
<string name="search_by_tags_or_persons__appspecific">Suche nach Tags oder Personen…</string>
|
<string name="search_by_tags_or_persons__appspecific">Suche nach Tags oder Personen…</string>
|
||||||
<string name="exit_app">App beenden</string>
|
<string name="exit_app">App beenden</string>
|
||||||
<string name="toggle_mobile_desktop_view">Mobil-/Desktopansicht umschalten</string>
|
<string name="toggle_mobile_desktop_view">Mobil-/Desktopansicht umschalten</string>
|
||||||
<string name="share_dotdotdot">Teilen…</string>
|
<string name="share_dotdotdot">Teilen…</string>
|
||||||
<string name="by_tags">nach Tags</string>
|
<string name="by_tags">nach Tags</string>
|
||||||
<string name="by_people">nach Personen</string>
|
<string name="by_people">nach Personen</string>
|
||||||
<string name="please_add_a_name">Füge einen Namen ein.</string>
|
<string name="please_add_a_name">Füge einen Namen ein.</string>
|
||||||
|
@ -82,9 +81,7 @@ nachträglich erteilen. Öffne dafür: Systemeinstellungen - Apps - dandelion*.
|
||||||
<string name="jump_to_last_visited_page_in_stream__appspecific">Zuletzt besuchte Seite im Stream aufrufen?</string>
|
<string name="jump_to_last_visited_page_in_stream__appspecific">Zuletzt besuchte Seite im Stream aufrufen?</string>
|
||||||
<string name="hide_statusbar_in_mainview">Statusleiste in Hauptansicht verstecken</string>
|
<string name="hide_statusbar_in_mainview">Statusleiste in Hauptansicht verstecken</string>
|
||||||
<string name="hide_statusbar">Statusleiste verstecken</string>
|
<string name="hide_statusbar">Statusleiste verstecken</string>
|
||||||
<string name="show_title_in_main_view">Titel in der Hauptansicht anzeigen</string>
|
|
||||||
<string name="show_title">Titel anzeigen</string>
|
<string name="show_title">Titel anzeigen</string>
|
||||||
<string name="launcher_shortcut">Launcher Verknüpfung</string>
|
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<string name="top_toolbar_loads_stream__appsp">Obere Werkzeugleiste lädt Stream</string>
|
<string name="top_toolbar_loads_stream__appsp">Obere Werkzeugleiste lädt Stream</string>
|
||||||
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Klicks auf leere Flächen der oberen Werkzeugleiste öffnen den Stream</string>
|
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Klicks auf leere Flächen der oberen Werkzeugleiste öffnen den Stream</string>
|
||||||
|
@ -197,16 +194,11 @@ nachträglich erteilen. Öffne dafür: Systemeinstellungen - Apps - dandelion*.
|
||||||
<!-- License & help (large amount of text) -->
|
<!-- License & help (large amount of text) -->
|
||||||
<string name="maintainers">Entwickler</string>
|
<string name="maintainers">Entwickler</string>
|
||||||
<string name="this_app_is_currently_developed_and_maintained_by_witharg">Diese Anwendung wird momentan entwickelt und betreut von <br><br>%1$s</string>
|
<string name="this_app_is_currently_developed_and_maintained_by_witharg">Diese Anwendung wird momentan entwickelt und betreut von <br><br>%1$s</string>
|
||||||
<string name="contributors">Beitragende</string>
|
<string name="contributors">Mitwirkende</string>
|
||||||
<string name="thank_you_witharg">%1$s<br><br>Vielen Dank!</string>
|
<string name="thank_you_witharg">%1$s<br><br>Vielen Dank!</string>
|
||||||
<string name="gnu_gplv3_license">GNU GPLv3+ Lizenz</string>
|
<string name="gnu_gplv3_license">GNU GPLv3+ Lizenz</string>
|
||||||
<string name="show_third_party_licenses">Drittanbieter-Bibliotheken</string>
|
<string name="show_third_party_licenses">Drittanbieter-Bibliotheken</string>
|
||||||
<string name="the_following_libraries_are_used">Die folgenden Bibliotheken werden genutzt:</string>
|
<string name="the_following_libraries_are_used">Die folgenden Bibliotheken werden genutzt:</string>
|
||||||
<string name="inspiration_from_leafpic__appspecific">Wir haben ein wenig bei LeafPic gespickt. Schaut euch das mal an, es handelt sich dabei auch um freie Software!</string>
|
<string name="inspiration_from_leafpic__appspecific">Wir haben ein wenig bei LeafPic gespickt. Schaut euch das mal an, es handelt sich dabei auch um freie Software!</string>
|
||||||
<string name="tell_me_more">Erzähl mir mehr</string>
|
<string name="tell_me_more">Erzähl mir mehr</string>
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Einschalten um YouTube Links in einer externen App zu öffnen</string>
|
|
||||||
<string name="youtube_links">YouTube Links</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Thema des Accounts ändern</string>
|
|
||||||
<string name="pull_to_refresh">Pull-To-Refresh</string>
|
|
||||||
<string name="pulling_down_on_top_of_page_to_refresh">In der Website von ganz oben nach unten ziehen um zu aktualisieren.\nDu musst die App neu starten damit die Änderungen wirksam werden.</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">Abrir el panel de navegación</string>
|
<string name="open_navdrawer">Abrir el panel de navegación</string>
|
||||||
<string name="close_navdrawer">Cerrar el panel de navegación</string>
|
<string name="close_navdrawer">Cerrar el panel de navegación</string>
|
||||||
<string name="reload">Refrescar</string>
|
<string name="reload">Refrescar</string>
|
||||||
<string name="close">Cerrar</string>
|
|
||||||
<string name="cancel">Cancelar</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Ajustes</string>
|
<string name="settings">Ajustes</string>
|
||||||
<string name="notifications">Notificaciones</string>
|
<string name="notifications">Notificaciones</string>
|
||||||
|
@ -52,7 +51,7 @@
|
||||||
<string name="search_by_tags_or_persons__appspecific">Buscar por etiquetas o por personas</string>
|
<string name="search_by_tags_or_persons__appspecific">Buscar por etiquetas o por personas</string>
|
||||||
<string name="exit_app">Salir de la aplicación</string>
|
<string name="exit_app">Salir de la aplicación</string>
|
||||||
<string name="toggle_mobile_desktop_view">Alternar vista de móvil/escritorio</string>
|
<string name="toggle_mobile_desktop_view">Alternar vista de móvil/escritorio</string>
|
||||||
<string name="share_dotdotdot">Compartir…</string>
|
<string name="share_dotdotdot">Compartir…</string>
|
||||||
<string name="by_tags">por etiquetas</string>
|
<string name="by_tags">por etiquetas</string>
|
||||||
<string name="by_people">por personas</string>
|
<string name="by_people">por personas</string>
|
||||||
<string name="please_add_a_name">Por favor, añade un nombre</string>
|
<string name="please_add_a_name">Por favor, añade un nombre</string>
|
||||||
|
@ -107,7 +106,7 @@
|
||||||
<!-- Notifications dropdown -->
|
<!-- Notifications dropdown -->
|
||||||
<string name="extended_notifications">Notificaciones extendidas</string>
|
<string name="extended_notifications">Notificaciones extendidas</string>
|
||||||
<string name="extendend_notifications_bell_description__appspecific">Extender la campana de notificaciones con un menú desplegable que muestra categorías de notificación</string>
|
<string name="extendend_notifications_bell_description__appspecific">Extender la campana de notificaciones con un menú desplegable que muestra categorías de notificación</string>
|
||||||
<string name="language_change_restart_description">Cambiar el idioma de esta aplicación. Reiniciar la aplicación para que se apliquen los cambios</string>
|
<string name="language_change_restart_description">Cambiar el idioma de esta aplicación. Reinicie la aplicación para que los cambios surtan efecto</string>
|
||||||
<string name="language">Idioma</string>
|
<string name="language">Idioma</string>
|
||||||
<string name="system_language">Idioma del sistema</string>
|
<string name="system_language">Idioma del sistema</string>
|
||||||
<!-- Font size -->
|
<!-- Font size -->
|
||||||
|
@ -192,16 +191,11 @@
|
||||||
<!-- License & help (large amount of text) -->
|
<!-- License & help (large amount of text) -->
|
||||||
<string name="maintainers">Mantenimiento</string>
|
<string name="maintainers">Mantenimiento</string>
|
||||||
<string name="this_app_is_currently_developed_and_maintained_by_witharg">Esta aplicación está siendo desarrollada y mantenida por < br >< br >%1$s</string>
|
<string name="this_app_is_currently_developed_and_maintained_by_witharg">Esta aplicación está siendo desarrollada y mantenida por < br >< br >%1$s</string>
|
||||||
<string name="contributors">Contribuidores</string>
|
<string name="contributors">Colaboradores</string>
|
||||||
<string name="thank_you_witharg">¡%1$s < br >< br > Gracias!</string>
|
<string name="thank_you_witharg">¡%1$s < br >< br > Gracias!</string>
|
||||||
<string name="gnu_gplv3_license">Licencia GNU GPLv3 +</string>
|
<string name="gnu_gplv3_license">Licencia GNU GPLv3 +</string>
|
||||||
<string name="show_third_party_licenses">Bibliotecas de terceros</string>
|
<string name="show_third_party_licenses">Bibliotecas de terceros</string>
|
||||||
<string name="the_following_libraries_are_used">Se utilizan las siguientes bibliotecas:</string>
|
<string name="the_following_libraries_are_used">Se utilizan las siguientes bibliotecas:</string>
|
||||||
<string name="inspiration_from_leafpic__appspecific">Tomamos algo de inspiración y código de LeafPic. ¡Venga, tomad prestado, es software libre también!</string>
|
<string name="inspiration_from_leafpic__appspecific">Tomamos algo de inspiración y código de LeafPic. ¡Venga, tomad prestado, es software libre también!</string>
|
||||||
<string name="tell_me_more">Saber más</string>
|
<string name="tell_me_more">Saber más</string>
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Habilitar para abrir enlaces de Youtube en aplicaciones externas</string>
|
|
||||||
<string name="youtube_links">Enlaces de YouTube</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Cambiar el tema de tu cuenta</string>
|
|
||||||
<string name="pull_to_refresh">Tirar para refrescar</string>
|
|
||||||
<string name="pulling_down_on_top_of_page_to_refresh">Deslizar hacia abajo la parte superior de la página para refrescar.\n Necesita reiniciar la aplicación para que los cambios surtan efecto.</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<string name="settings">Mga Tanawin</string>
|
|
||||||
<string name="search">Hanapin</string>
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<string name="appearance">Ayos</string>
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">Ouvrir le tiroir de navigation</string>
|
<string name="open_navdrawer">Ouvrir le tiroir de navigation</string>
|
||||||
<string name="close_navdrawer">Fermer le tiroir de navigation</string>
|
<string name="close_navdrawer">Fermer le tiroir de navigation</string>
|
||||||
<string name="reload">Rafraîchir</string>
|
<string name="reload">Rafraîchir</string>
|
||||||
<string name="close">Fermer</string>
|
|
||||||
<string name="cancel">Annuler</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Paramètres</string>
|
<string name="settings">Paramètres</string>
|
||||||
<string name="notifications">Notifications</string>
|
<string name="notifications">Notifications</string>
|
||||||
|
@ -52,7 +51,7 @@
|
||||||
<string name="search_by_tags_or_persons__appspecific">Recherche par tags ou par personnes</string>
|
<string name="search_by_tags_or_persons__appspecific">Recherche par tags ou par personnes</string>
|
||||||
<string name="exit_app">Quitter l\'application</string>
|
<string name="exit_app">Quitter l\'application</string>
|
||||||
<string name="toggle_mobile_desktop_view">Activer/désactiver la vue bureau/mobile</string>
|
<string name="toggle_mobile_desktop_view">Activer/désactiver la vue bureau/mobile</string>
|
||||||
<string name="share_dotdotdot">Partager…</string>
|
<string name="share_dotdotdot">Partager…</string>
|
||||||
<string name="by_tags">par tags</string>
|
<string name="by_tags">par tags</string>
|
||||||
<string name="by_people">par personne</string>
|
<string name="by_people">par personne</string>
|
||||||
<string name="please_add_a_name">Veuillez ajouter un nom</string>
|
<string name="please_add_a_name">Veuillez ajouter un nom</string>
|
||||||
|
@ -107,7 +106,7 @@
|
||||||
<!-- Notifications dropdown -->
|
<!-- Notifications dropdown -->
|
||||||
<string name="extended_notifications">Notifications étendues</string>
|
<string name="extended_notifications">Notifications étendues</string>
|
||||||
<string name="extendend_notifications_bell_description__appspecific">Étendre la cloche de notifications avec un menu déroulant qui affiche les catégories de notification</string>
|
<string name="extendend_notifications_bell_description__appspecific">Étendre la cloche de notifications avec un menu déroulant qui affiche les catégories de notification</string>
|
||||||
<string name="language_change_restart_description">Changer la langue de l\'interface. Vous devrez redémarrer l\'application pour que ce changement soit pris en compte</string>
|
<string name="language_change_restart_description">Change la langue de l\'application. Redémarrez l\'application pour que les changements prennent effet</string>
|
||||||
<string name="language">Langue</string>
|
<string name="language">Langue</string>
|
||||||
<string name="system_language">Langue du système</string>
|
<string name="system_language">Langue du système</string>
|
||||||
<!-- Font size -->
|
<!-- Font size -->
|
||||||
|
@ -199,9 +198,4 @@
|
||||||
<string name="the_following_libraries_are_used">Les bibliothèques suivantes sont utilisées :</string>
|
<string name="the_following_libraries_are_used">Les bibliothèques suivantes sont utilisées :</string>
|
||||||
<string name="inspiration_from_leafpic__appspecific">Nous avons pris des inspirations et du code de LeafPic. Allez voir, c\'est aussi un logiciel libre !</string>
|
<string name="inspiration_from_leafpic__appspecific">Nous avons pris des inspirations et du code de LeafPic. Allez voir, c\'est aussi un logiciel libre !</string>
|
||||||
<string name="tell_me_more">En savoir plus</string>
|
<string name="tell_me_more">En savoir plus</string>
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Autoriser l\'ouverture des liens Youtube par une appli externe</string>
|
|
||||||
<string name="youtube_links">Liens Youtube</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Changer le thème de votre compte</string>
|
|
||||||
<string name="pull_to_refresh">Tirer vers le bas pour mettre à jour</string>
|
|
||||||
<string name="pulling_down_on_top_of_page_to_refresh">Tirez depuis le haut de la page vers le bas pour l\'actualiser.\nVous devez redémarrer l\'application pour que ces changements prennent effet.</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">Abrir cadro de navegación</string>
|
<string name="open_navdrawer">Abrir cadro de navegación</string>
|
||||||
<string name="close_navdrawer">Pechar cadro de navegación</string>
|
<string name="close_navdrawer">Pechar cadro de navegación</string>
|
||||||
<string name="reload">Actualizar</string>
|
<string name="reload">Actualizar</string>
|
||||||
<string name="close">Pechar</string>
|
|
||||||
<string name="cancel">Cancelar</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">Axustes</string>
|
<string name="settings">Axustes</string>
|
||||||
<string name="notifications">Notificacións</string>
|
<string name="notifications">Notificacións</string>
|
||||||
<string name="conversations">Conversas</string>
|
<string name="conversations">Conversa</string>
|
||||||
<string name="stream">Cronoloxía</string>
|
<string name="stream">Fío de comentarios</string>
|
||||||
<string name="profile">Perfil</string>
|
<string name="profile">Perfil</string>
|
||||||
<string name="aspects">Aspecto</string>
|
<string name="aspects">Aspecto</string>
|
||||||
<string name="activities">Actividades</string>
|
<string name="activities">Actividades</string>
|
||||||
|
@ -29,10 +28,10 @@
|
||||||
<string name="deleteme_____1">Gústame</string>
|
<string name="deleteme_____1">Gústame</string>
|
||||||
<string name="mentioned">Mencionado</string>
|
<string name="mentioned">Mencionado</string>
|
||||||
<string name="reshared">Compartido</string>
|
<string name="reshared">Compartido</string>
|
||||||
<string name="started_sharing">Xa compartes</string>
|
<string name="started_sharing">Comezou a compartir</string>
|
||||||
<!-- Pod Activity -->
|
<!-- Pod Activity -->
|
||||||
<string name="could_not_retrieve_list_of_pods__appspecific">Problema: non se obtivo a lista de nodos!</string>
|
<string name="could_not_retrieve_list_of_pods__appspecific">Problema: non se obtivo a lista de nodos!</string>
|
||||||
<string name="sorry_need_to_be_connected_to_internet">Desculpa, tes que ter conexión a internet para esto</string>
|
<string name="sorry_need_to_be_connected_to_internet">Desculpe, precisa unha conexión a internet para esa tarefa</string>
|
||||||
<string name="confirmation">Confirmación</string>
|
<string name="confirmation">Confirmación</string>
|
||||||
<string name="do_you_want_to_exit">Quere saír?</string>
|
<string name="do_you_want_to_exit">Quere saír?</string>
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
||||||
|
@ -50,12 +49,12 @@
|
||||||
<string name="new_post">Nova mensaxe</string>
|
<string name="new_post">Nova mensaxe</string>
|
||||||
<string name="go_to_top">Ir arriba</string>
|
<string name="go_to_top">Ir arriba</string>
|
||||||
<string name="search_by_tags_or_persons__appspecific">Buscar persoas ou etiquetas</string>
|
<string name="search_by_tags_or_persons__appspecific">Buscar persoas ou etiquetas</string>
|
||||||
<string name="exit_app">Saír da app</string>
|
<string name="exit_app">Saír do app</string>
|
||||||
<string name="toggle_mobile_desktop_view">Vista móbil/escritorio</string>
|
<string name="toggle_mobile_desktop_view">Vista móbil/escritorio</string>
|
||||||
<string name="share_dotdotdot">Compartir…</string>
|
<string name="share_dotdotdot">Compartir…</string>
|
||||||
<string name="by_tags">Etiquetas</string>
|
<string name="by_tags">Etiquetas</string>
|
||||||
<string name="by_people">Persoas</string>
|
<string name="by_people">Persoas</string>
|
||||||
<string name="please_add_a_name">Por favor, engade un nome</string>
|
<string name="please_add_a_name">Por favor, engada un nome</string>
|
||||||
<string name="share_link_address">Compartir ligazón</string>
|
<string name="share_link_address">Compartir ligazón</string>
|
||||||
<string name="save_image">Gardar imaxe</string>
|
<string name="save_image">Gardar imaxe</string>
|
||||||
<string name="share_image">Compartir imaxe</string>
|
<string name="share_image">Compartir imaxe</string>
|
||||||
|
@ -65,19 +64,19 @@
|
||||||
<!-- More from MainActivity -->
|
<!-- More from MainActivity -->
|
||||||
<string name="unable_to_load_image">Non se cargou a imaxe</string>
|
<string name="unable_to_load_image">Non se cargou a imaxe</string>
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
<string name="screenshot_permission__appspecific">Debes permitir \"Permiso de acceso a almacenamento\" para gardar capturas. Podes
|
<string name="screenshot_permission__appspecific">Debe permitir \"Permiso de acceso a almacenamento\" para gardar capturas. Pode
|
||||||
pechar a aplicación ou reiniciar o dispositivo. Se non permites acceder ao almacenamento pero queres utilizar máis tarde a captura de pantalla, poderás permitir posteriormente o acceso na sección de permisos do dispositivo onde podes activar o \"permiso de acceso a almacenamento\" para dandelion*.</string>
|
pechar a aplicación ou reiniciar o dispositivo. Si non permite acceder ao almacenamento pero que utilizar máis tarde a captura de pantalla, poderá permitir posteriormente o acceso na sección de permisos do dispositivo onde pode activar o \"permiso de acceso a almacenamento\" para dandelion*.</string>
|
||||||
<string name="image_permission_description__appspecific">Tes que permitir \"Permiso de acceso a almacenamento\" para gardar/subir imaxes. Despois de iso deberías
|
<string name="image_permission_description__appspecific">Ten que permitir \"Permiso de acceso a almacenamento\" para gardar/subir imaxes. Despois de iso debería
|
||||||
pechar a aplicación ou reiniciar o dispositivo. Se non permites acceder ao almacenamento, para poder gardar imaxes posteriormente, deberás abrir: preferencias do sistema - apps - dandelion* no dispositivo.
|
pechar a aplicación ou reiniciar o dispositivo. Se non permite acceder ao almacenamento, para poder gardar imaxes posteriormente, deberá abrir: preferencias do sistema - apps - dandelion* no dispositivo.
|
||||||
Na sección de permisos podes activar o \"permiso de escritura no almacenamento\".</string>
|
Na sección de permisos pode activar o \"permiso de escritura no almacenamento\".</string>
|
||||||
<string name="permission_denied">Permiso denegado.</string>
|
<string name="permission_denied">Permiso denegado.</string>
|
||||||
<string name="permission_granted_try_again">Permiso concedido. Inténtao de novo.</string>
|
<string name="permission_granted_try_again">Permiso concedido. Inténteo de novo.</string>
|
||||||
<string name="custom_pod">Nodo personalizado</string>
|
<string name="custom_pod">Nodo personalizado</string>
|
||||||
<string name="pod_name">Nome do nodo</string>
|
<string name="pod_name">Nome do nodo</string>
|
||||||
<string name="protocol">Protocolo</string>
|
<string name="protocol">Protocolo</string>
|
||||||
<string name="pod_address">Enderezo do nodo</string>
|
<string name="pod_address">Enderezo do nodo</string>
|
||||||
<string name="missing_value">Faltan datos</string>
|
<string name="missing_value">Faltan datos</string>
|
||||||
<string name="jump_to_last_visited_page_in_stream__appspecific">Ir a última páxina lida na conversa?</string>
|
<string name="jump_to_last_visited_page_in_stream__appspecific">Ir a última paxina lida na conversa?</string>
|
||||||
<string name="hide_statusbar_in_mainview">Agochar a barra de estado na vista principal</string>
|
<string name="hide_statusbar_in_mainview">Agochar a barra de estado na vista principal</string>
|
||||||
<string name="hide_statusbar">Agochar barra de estado</string>
|
<string name="hide_statusbar">Agochar barra de estado</string>
|
||||||
<string name="show_title_in_main_view">Mostrar título na vista principal</string>
|
<string name="show_title_in_main_view">Mostrar título na vista principal</string>
|
||||||
|
@ -85,7 +84,7 @@
|
||||||
<string name="launcher_shortcut">Atallo do lanzador</string>
|
<string name="launcher_shortcut">Atallo do lanzador</string>
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<string name="top_toolbar_loads_stream__appsp">A barra superior carga a conversa</string>
|
<string name="top_toolbar_loads_stream__appsp">A barra superior carga a conversa</string>
|
||||||
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Preme nun espazo baleiro na barra superior para abrir a conversa</string>
|
<string name="click_empty_space_top_toolbar_load_stream__appspecific">Pulse nun espazo baldeiro na barra superior para abrir a conversa</string>
|
||||||
<!-- Category Titles -->
|
<!-- Category Titles -->
|
||||||
<string name="appearance">Aparencia</string>
|
<string name="appearance">Aparencia</string>
|
||||||
<string name="network">Rede</string>
|
<string name="network">Rede</string>
|
||||||
|
@ -94,13 +93,13 @@
|
||||||
<!-- Visuals -->
|
<!-- Visuals -->
|
||||||
<!-- Navigiation Slider -->
|
<!-- Navigiation Slider -->
|
||||||
<string name="navigation_drawer">Cadro de navegación</string>
|
<string name="navigation_drawer">Cadro de navegación</string>
|
||||||
<string name="control_visibility_of_entries_nav_drawer">Controla a visibiidade das entradas no cadro de navegación</string>
|
<string name="control_visibility_of_entries_nav_drawer">Controle a visibiidade das entradas no cadro de navegación</string>
|
||||||
<string name="user">Usuaria</string>
|
<string name="user">Usuaria</string>
|
||||||
<string name="general">Xeral</string>
|
<string name="general">Xeral</string>
|
||||||
<string name="admin">Admin</string>
|
<string name="admin">Admin</string>
|
||||||
<!-- Themes -->
|
<!-- Themes -->
|
||||||
<string name="theme_and_colors">Decorado e cores</string>
|
<string name="theme_and_colors">Decorado e cores</string>
|
||||||
<string name="control_which_colors_are_used_in_app">Escolle qué cores se utilizan na aplicación</string>
|
<string name="control_which_colors_are_used_in_app">Estableza qué cores se utilizan na aplicación</string>
|
||||||
<string name="primary_colors">Cor primaria</string>
|
<string name="primary_colors">Cor primaria</string>
|
||||||
<string name="colors_of_toolbars">Cor das barras de ferramentas</string>
|
<string name="colors_of_toolbars">Cor das barras de ferramentas</string>
|
||||||
<string name="accent_color">Cor de énfase</string>
|
<string name="accent_color">Cor de énfase</string>
|
||||||
|
@ -110,7 +109,7 @@
|
||||||
<!-- Notifications dropdown -->
|
<!-- Notifications dropdown -->
|
||||||
<string name="extended_notifications">Notificacións extendidas</string>
|
<string name="extended_notifications">Notificacións extendidas</string>
|
||||||
<string name="extendend_notifications_bell_description__appspecific">Extender a icona da campá de notificación con un menú desplegable que mostre a categoría das notificacións</string>
|
<string name="extendend_notifications_bell_description__appspecific">Extender a icona da campá de notificación con un menú desplegable que mostre a categoría das notificacións</string>
|
||||||
<string name="language_change_restart_description">Cambiar o idioma de esta aplicación. Reinicia para que se aplique o troco</string>
|
<string name="language_change_restart_description">Cambiar o idioma de esta aplicación. Reinicie para que se aplique o troco</string>
|
||||||
<string name="language">Idioma</string>
|
<string name="language">Idioma</string>
|
||||||
<string name="system_language">Idioma do sistema</string>
|
<string name="system_language">Idioma do sistema</string>
|
||||||
<!-- Font size -->
|
<!-- Font size -->
|
||||||
|
@ -134,22 +133,22 @@
|
||||||
<string name="load_proxy_settins_for_tor">Cargar axustes proxy para Tor (Orbot) HTTP Proxy</string>
|
<string name="load_proxy_settins_for_tor">Cargar axustes proxy para Tor (Orbot) HTTP Proxy</string>
|
||||||
<string name="proxy">Proxy</string>
|
<string name="proxy">Proxy</string>
|
||||||
<string name="enable_proxy">Habilitar Proxy</string>
|
<string name="enable_proxy">Habilitar Proxy</string>
|
||||||
<string name="proxy_dandelion_traffic__appspecific">Proxy para o tráfico de dandelion* para saltar cortalumes.\nPodería precisar reinicio. Esto podería non funcionar nalgúns móbiles.</string>
|
<string name="proxy_dandelion_traffic__appspecific">Proxy para o tráfico de dandelion* para saltar cortalumes.\nPodería precisar reinicio. Esto podería non funcionar en algúns móbiles.</string>
|
||||||
<string name="host">Servidor</string>
|
<string name="host">Servidor</string>
|
||||||
<string name="port">Porto</string>
|
<string name="port">Porto</string>
|
||||||
<string name="app_needs_restart_to_disable_proxy_usage">Precisa reiniciar a app para desactivar o uso do proxy</string>
|
<string name="app_needs_restart_to_disable_proxy_usage">Precisa reiniciar o app para deshabilitar o uso do proxy</string>
|
||||||
<string name="orbot_proxy_preset_loaded">Cargadas as preferencias do proxy Orbot</string>
|
<string name="orbot_proxy_preset_loaded">Cargadas as preferencias do proxy Orbot</string>
|
||||||
<!-- Chrome custom tabs -->
|
<!-- Chrome custom tabs -->
|
||||||
<string name="open_external_links_with_chrome_custom_tabs_description">Abrir ligazóns externas con Chrome Custom Tabs. Chromium ou Google Chrome ten que estar instalado para utilizar esta característica.\nIMPORTANTE: Chrome Custom Tabs non utiliza os servidores proxy configurados!</string>
|
<string name="open_external_links_with_chrome_custom_tabs_description">Abrir ligazóns externas con Chrome Custom Tabs. Chromium ou Google Chrome ten que estar instalado para utilizar esta característica.\nIMPORTANTE: Chrome Custom Tabs non utiliza os servidores proxy configurados!</string>
|
||||||
<!-- Diaspora Settings -->
|
<!-- Diaspora Settings -->
|
||||||
<string name="personal_settings">Axustes personais</string>
|
<string name="personal_settings">Axustes personais</string>
|
||||||
<string name="open_diaspora_account_settings__appspecific">Abrir os axustes da conta diaspora*</string>
|
<string name="open_diaspora_account_settings__appspecific">Abrir os axustes da conta diaspora*</string>
|
||||||
<string name="manage_your_contact_list">Xestiona a lista de contactos</string>
|
<string name="manage_your_contact_list">Xestione a súa lista de contactos</string>
|
||||||
<string name="manage_hashtags">Xestionar etiquetas</string>
|
<string name="manage_hashtags">Xestionar etiquetas</string>
|
||||||
<string name="unfollow_already_followed_hashtags__appspecific">Deixar de seguir etiquetas que segues</string>
|
<string name="unfollow_already_followed_hashtags__appspecific">Deixar de seguir etiquetas que segue</string>
|
||||||
<string name="change_account">Mudar de conta</string>
|
<string name="change_account">Mudar de conta</string>
|
||||||
<string name="loug_warning_description__appspecific">Eliminar os datos locais da sesión e cambiar a outro nodo/conta de diaspora*</string>
|
<string name="loug_warning_description__appspecific">Eliminar os datos locais da sesión e cambiar a outro nodo/conta de diaspora*</string>
|
||||||
<string name="logout_warning_description">Esto eliminará todas as cookies e datos de sesión. Seguro que queres mudar de conta?</string>
|
<string name="logout_warning_description">Esto eliminará todas as cookies e datos de sesión. Seguro que quere mudar de conta?</string>
|
||||||
<string name="clear_cache">Limpar cache</string>
|
<string name="clear_cache">Limpar cache</string>
|
||||||
<string name="clear_webview_cache">Limpar a cache da VistaWeb</string>
|
<string name="clear_webview_cache">Limpar a cache da VistaWeb</string>
|
||||||
<string name="intellihide_toolbars__appspecific">Agochar automáticamente as barras superior e inferior mentras desplaza</string>
|
<string name="intellihide_toolbars__appspecific">Agochar automáticamente as barras superior e inferior mentras desplaza</string>
|
||||||
|
@ -159,9 +158,9 @@
|
||||||
<!-- More -->
|
<!-- More -->
|
||||||
<string name="miscellaneous">Varios</string>
|
<string name="miscellaneous">Varios</string>
|
||||||
<string name="full_reset">Restablecer completamente</string>
|
<string name="full_reset">Restablecer completamente</string>
|
||||||
<string name="wipe_settings_and_logout">Eliminar todolos axustes locais da app e desconectar todas as contas</string>
|
<string name="wipe_settings_and_logout">Eliminar todas os axustes locais do app e desconectar todas as contas</string>
|
||||||
<string name="wipe_settings_warning__appspecific">Esto restablecerá todos os axustes da aplicación ao valor por omisión e desconectarate de todolos nodos. As imaxes descargadas permanecerán. Seguro que queres proceder?</string>
|
<string name="wipe_settings_warning__appspecific">Esto restablecerá todos os axustes da aplicación ao valor por omisión e desconectarao de todos os nodos. As súas imaxes descargadas permanecerán. Seguro que quere proceder?</string>
|
||||||
<string name="enable_basic_adblocker_description">Activar un AdBlocker básico. Poderían verse anuncios por exemplo en vistas incrustadas</string>
|
<string name="enable_basic_adblocker_description">Habilitar un AdBlocker básico. Poderían verse anuncios por exemplo en vistas incrustadas</string>
|
||||||
<string name="block_advertisments">Bloquear publicidade</string>
|
<string name="block_advertisments">Bloquear publicidade</string>
|
||||||
<string name="about">Sobre</string>
|
<string name="about">Sobre</string>
|
||||||
<string name="license">Licenza</string>
|
<string name="license">Licenza</string>
|
||||||
|
@ -171,27 +170,27 @@
|
||||||
<string name="diaspora_pod__appspecific">Nodo diaspora*</string>
|
<string name="diaspora_pod__appspecific">Nodo diaspora*</string>
|
||||||
<string name="debug_log">Rexistro de depuración</string>
|
<string name="debug_log">Rexistro de depuración</string>
|
||||||
<string name="debug_log_verbose">Rexistro de depuración (polo miúdo)</string>
|
<string name="debug_log_verbose">Rexistro de depuración (polo miúdo)</string>
|
||||||
<string name="app_version_with_arg">Versión da App: %1$s</string>
|
<string name="app_version_with_arg">Versión do App: %1$s</string>
|
||||||
<string name="android_version_witharg">Versión Android: %1$s</string>
|
<string name="android_version_witharg">Versión Android: %1$s</string>
|
||||||
<string name="device_name_witharg">Nome do dispositivo: %1$s</string>
|
<string name="device_name_witharg">Nome do dispositivo: %1$s</string>
|
||||||
<string name="code_name_witharg">Alcume: %1$s</string>
|
<string name="code_name_witharg">Alcume: %1$s</string>
|
||||||
<string name="pod_profile_name_witharg__appspecific">Nome do perfil do nodo: %1$s</string>
|
<string name="pod_profile_name_witharg__appspecific">Nome do perfil do nodo: %1$s</string>
|
||||||
<string name="pod_domain_witharg__appspecific">Dominio do nodo: %1$s</string>
|
<string name="pod_domain_witharg__appspecific">Dominio do nodo: %1$s</string>
|
||||||
<string name="debug_log_copied_to_clipboard">Ficheiro de depuración copiado ao portapapeis</string>
|
<string name="debug_log_copied_to_clipboard">Ficheiro de depuración copiado ao portapapeis</string>
|
||||||
<string name="dandelion_is_your_companion__appspecific">dandelion* é a túa aplicación para a rede social diaspora*. Engade características como barras de ferramentas e soporte para servidores proxy como a rede Tor.</string>
|
<string name="dandelion_is_your_companion__appspecific">dandelion* é a súa aplicación para a rede social diaspora*. Engade características como barras de ferramentas e soporte para servidores proxy como a rede Tor para a súa experiencia social.</string>
|
||||||
<string name="contribute_code">Contribúa ao código!</string>
|
<string name="contribute_code">Contribúa ao código!</string>
|
||||||
<string name="dandelion_is_developed_as_foss__appspecific">dandelion* é desenvolta libre, libre de Liberdade, e segue o espíritu que marca o proxecto diaspora*. Se queres contribuír, adiante! Por agora somos un equipo pequeno, así que agradecemos calquer tipo de axuda!</string>
|
<string name="dandelion_is_developed_as_foss__appspecific">dandelion* é desenvolto libre, libre de Liberdade, e segue o espíritu que marca o proxecto diaspora*. Se quere contribuír, adiante! Por agora somos un equipo pequeno, así que agradecemos calquer tipo de axuda!</string>
|
||||||
<string name="get_the_source">Aquí as fontes</string>
|
<string name="get_the_source">Obteña as fontes</string>
|
||||||
<string name="translate_the_app">Traduce a app!</string>
|
<string name="translate_the_app">Traduza o app!</string>
|
||||||
<string name="app_not_available_in_your_lang_translate_with_stringlate">Non está a aplicación no teu idioma? Podes cambiar eso! Por qué non nos axudas traducíndoa? Utilizamos a plataforma Crowdin para que calquera poida traducir a app.</string>
|
<string name="app_not_available_in_your_lang_translate_with_stringlate">Non está a aplicación no seu idioma? Pode cambiar eso! Por qué non nos axuda traducíndoa? Utilizamos a plataforma github para que calquera poida traducir a app.</string>
|
||||||
<string name="let_me_translate">Deixame traducir</string>
|
<string name="let_me_translate">Deixame traducir</string>
|
||||||
<string name="give_feedback">Danos a túa opinión!</string>
|
<string name="give_feedback">Qué lle parece!</string>
|
||||||
<string name="dandelion_still_in_development__appspecific">dandelion* aínda está en desenvolvemento, asi que se tes suxestións de calquer tipo ou valoración, por favor usa o noso xestor de errros para facérnolo saber!</string>
|
<string name="dandelion_still_in_development__appspecific">dandelion* aínda está en desenvolvemento, asi que si ten suxerencias de calquer tipo o valoración, por favor utilice o noso xestor de erros para facérnolo saber!</string>
|
||||||
<string name="report_bugs">Reporte erros</string>
|
<string name="report_bugs">Reporte erros</string>
|
||||||
<string name="spread_the_word">Difunde!</string>
|
<string name="spread_the_word">Difunda!</string>
|
||||||
<string name="tell_your_friends_about_diaspora__appspecific">Dille aos teus amigos e familiares que utilizas diaspora* e #dandelion! Por qué non escribir sobre a experiencia? Encantaríanos saber de ti!</string>
|
<string name="tell_your_friends_about_diaspora__appspecific">Dígalle aos seus amigos e familiares que utiliza diaspora* e #dandelion! Por qué no escribir sobre a experiencia? Encantaríanos saber de vostede!</string>
|
||||||
<string name="share_the_app">Comparte a aplicación</string>
|
<string name="share_the_app">Comparta a aplicación</string>
|
||||||
<string name="hey_checkout_dandelion_tag__appspecific">Ei!! Olla #dandelion! %1$s</string>
|
<string name="hey_checkout_dandelion_tag__appspecific">Ei!! Olla a #dandelion! %1$s</string>
|
||||||
<!-- License & help (large amount of text) -->
|
<!-- License & help (large amount of text) -->
|
||||||
<string name="maintainers">Mantedores</string>
|
<string name="maintainers">Mantedores</string>
|
||||||
<string name="this_app_is_currently_developed_and_maintained_by_witharg">Esta aplicación está a ser desenvolta e mantida por <br><br>%1$s</string>
|
<string name="this_app_is_currently_developed_and_maintained_by_witharg">Esta aplicación está a ser desenvolta e mantida por <br><br>%1$s</string>
|
||||||
|
@ -202,9 +201,4 @@
|
||||||
<string name="the_following_libraries_are_used">Utilízase o seguinte código:</string>
|
<string name="the_following_libraries_are_used">Utilízase o seguinte código:</string>
|
||||||
<string name="inspiration_from_leafpic__appspecific">Inspirámonos e collemos código de LeafPic. Bótalle un ollo, tamén é software libre!</string>
|
<string name="inspiration_from_leafpic__appspecific">Inspirámonos e collemos código de LeafPic. Bótalle un ollo, tamén é software libre!</string>
|
||||||
<string name="tell_me_more">Cóntame máis</string>
|
<string name="tell_me_more">Cóntame máis</string>
|
||||||
<string name="enable_to_open_youtube_links_on_external_app">Activar para abrir vídeos YouTube nunha app externa</string>
|
|
||||||
<string name="youtube_links">Ligazóns YouTube</string>
|
|
||||||
<string name="change_the_theme_of_your_account">Cambiar o decorado da túa conta</string>
|
|
||||||
<string name="pull_to_refresh">Tira para actualizar</string>
|
|
||||||
<string name="pulling_down_on_top_of_page_to_refresh">Tirar hacia abaixo na parte superior da páxina.\nDebes reiniciar a app para que os cambios se apliquen.</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="open_navdrawer">नेविगेशन ड्रॉवर खोलें</string>
|
|
||||||
<string name="close_navdrawer">नेविगेशन ड्रॉवर को बंद करें</string>
|
|
||||||
<!-- Common Words -->
|
<!-- Common Words -->
|
||||||
<string name="settings">सेटिंग्स</string>
|
<string name="settings">सेटिंग्स</string>
|
||||||
<string name="search">खोजें</string>
|
<string name="search">खोजें</string>
|
||||||
|
@ -15,7 +14,6 @@
|
||||||
<!-- More from MainActivity -->
|
<!-- More from MainActivity -->
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
<string name="hide_statusbar">स्थिति पट्टी छुपाएँ</string>
|
<string name="hide_statusbar">स्थिति पट्टी छुपाएँ</string>
|
||||||
<string name="show_title">शीर्षक दिखाएं</string>
|
|
||||||
<!-- Operability -->
|
<!-- Operability -->
|
||||||
<!-- Category Titles -->
|
<!-- Category Titles -->
|
||||||
<string name="appearance">दिखावट</string>
|
<string name="appearance">दिखावट</string>
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Application -->
|
<!-- Application -->
|
||||||
<string name="reload">Újratölt</string>
|
<string name="reload">Újratölt</string>
|
||||||
|
@ -48,7 +49,7 @@
|
||||||
<string name="search_by_tags_or_persons__appspecific">Címkék vagy emberek keresése</string>
|
<string name="search_by_tags_or_persons__appspecific">Címkék vagy emberek keresése</string>
|
||||||
<string name="exit_app">Kilépés az alkalmazásból</string>
|
<string name="exit_app">Kilépés az alkalmazásból</string>
|
||||||
<string name="toggle_mobile_desktop_view">Mobil-/asztali mód</string>
|
<string name="toggle_mobile_desktop_view">Mobil-/asztali mód</string>
|
||||||
<string name="share_dotdotdot">Megosztás…</string>
|
<string name="share_dotdotdot">Megosztás…</string>
|
||||||
<string name="by_tags">címkékre</string>
|
<string name="by_tags">címkékre</string>
|
||||||
<string name="by_people">emberekre</string>
|
<string name="by_people">emberekre</string>
|
||||||
<string name="please_add_a_name">Kérlek, adj meg egy nevet</string>
|
<string name="please_add_a_name">Kérlek, adj meg egy nevet</string>
|
||||||
|
@ -152,7 +153,7 @@
|
||||||
<string name="enable_basic_adblocker_description">Alap hirdetésblokkoló (AdBlocker) engedélyezése. Reklámok jelenhetnek meg pl. a beépített megjelenítéseknél</string>
|
<string name="enable_basic_adblocker_description">Alap hirdetésblokkoló (AdBlocker) engedélyezése. Reklámok jelenhetnek meg pl. a beépített megjelenítéseknél</string>
|
||||||
<string name="block_advertisments">Hirdetések blokkolása</string>
|
<string name="block_advertisments">Hirdetések blokkolása</string>
|
||||||
<string name="about">Névjegy</string>
|
<string name="about">Névjegy</string>
|
||||||
<string name="license">Licenc</string>
|
<string name="license">Licensz</string>
|
||||||
<string name="debugging">Hibakeresés</string>
|
<string name="debugging">Hibakeresés</string>
|
||||||
<string name="application">Alkalmazás</string>
|
<string name="application">Alkalmazás</string>
|
||||||
<string name="device">Eszköz</string>
|
<string name="device">Eszköz</string>
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Application -->
|
|
||||||
<!-- Common Words -->
|
|
||||||
<!-- Notifications dropdown menu -->
|
|
||||||
<!-- Pod Activity -->
|
|
||||||
<!-- Drawer, Menu, Toolbar, ContextMenu -->
|
|
||||||
<!-- More from MainActivity -->
|
|
||||||
<!-- Permissions -->
|
|
||||||
<!-- Operability -->
|
|
||||||
<!-- Category Titles -->
|
|
||||||
<!-- Visuals -->
|
|
||||||
<!-- Navigiation Slider -->
|
|
||||||
<!-- Themes -->
|
|
||||||
<!-- Notifications dropdown -->
|
|
||||||
<!-- Font size -->
|
|
||||||
<!-- Load images -->
|
|
||||||
<!-- Screen rotation -->
|
|
||||||
<!-- Proxy -->
|
|
||||||
<!-- Chrome custom tabs -->
|
|
||||||
<!-- Diaspora Settings -->
|
|
||||||
<!-- More -->
|
|
||||||
<!-- License & help (large amount of text) -->
|
|
||||||
</resources>
|
|