From 0f12bf15575ca1bc93ce319cd29708510c9fb47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Sch=C3=BCller?= Date: Sun, 21 Jun 2020 17:06:30 +0200 Subject: [PATCH 1/2] Release v1.0.38 (#174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translated using Weblate (Italian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 38.7% (125 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 48.0% (155 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (German) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/de/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Bengali) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Spanish) Currently translated at 42.1% (136 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/es/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Persian) Currently translated at 40.2% (130 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fa/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Russian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * update library and more (#160) * download files with friendly name (not video ID) * Update Picasso library FIX : add extension in downloaded filename. download files with friendly name (not video ID) * Update Gradle Add 0.75x and 1.25x to play speed * Release v1.0.35 * try to fix 'cannot make a new request because the previous response ... ' error (#164) * Translations (#163) * Translated using Weblate (Italian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 38.7% (125 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 48.0% (155 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (German) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/de/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Bengali) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Spanish) Currently translated at 42.1% (136 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/es/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Persian) Currently translated at 40.2% (130 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fa/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Russian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * update library and more (#160) * download files with friendly name (not video ID) * Update Picasso library FIX : add extension in downloaded filename. download files with friendly name (not video ID) * Update Gradle Add 0.75x and 1.25x to play speed * Release v1.0.35 Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller * try to fix 'cannot make a new request because the previous response is still open' when login. Co-authored-by: Stefan Schüller Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller * Release 1.0.36 * Translated using Weblate (Arabic) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ar/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Dutch) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/nl/ * Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hant/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Italian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/it/ * Master (#170) * Translations (#163) * Translated using Weblate (Italian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 38.7% (125 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 48.0% (155 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (German) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/de/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Bengali) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Spanish) Currently translated at 42.1% (136 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/es/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Persian) Currently translated at 40.2% (130 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fa/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Russian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * update library and more (#160) * download files with friendly name (not video ID) * Update Picasso library FIX : add extension in downloaded filename. download files with friendly name (not video ID) * Update Gradle Add 0.75x and 1.25x to play speed * Release v1.0.35 Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller * Release 1.0.36 (#166) * Translated using Weblate (Italian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 38.7% (125 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 48.0% (155 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (German) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/de/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Bengali) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Spanish) Currently translated at 42.1% (136 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/es/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Persian) Currently translated at 40.2% (130 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fa/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Russian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * update library and more (#160) * download files with friendly name (not video ID) * Update Picasso library FIX : add extension in downloaded filename. download files with friendly name (not video ID) * Update Gradle Add 0.75x and 1.25x to play speed * Release v1.0.35 * try to fix 'cannot make a new request because the previous response ... ' error (#164) * Translations (#163) * Translated using Weblate (Italian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 38.7% (125 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 48.0% (155 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/zh_Hans/ * Translated using Weblate (German) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/de/ * Translated using Weblate (French) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fr/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Russian) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * Translated using Weblate (Bengali) Currently translated at 99.3% (321 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Spanish) Currently translated at 42.1% (136 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/es/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Persian) Currently translated at 40.2% (130 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/fa/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 99.6% (322 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Bengali) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/bn/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Polish) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/pl/ * Translated using Weblate (Russian) Currently translated at 100.0% (323 of 323 strings) Translation: PeerTube/Android Translate-URL: https://hosted.weblate.org/projects/peertube/android/ru/ * update library and more (#160) * download files with friendly name (not video ID) * Update Picasso library FIX : add extension in downloaded filename. download files with friendly name (not video ID) * Update Gradle Add 0.75x and 1.25x to play speed * Release v1.0.35 Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller * try to fix 'cannot make a new request because the previous response is still open' when login. Co-authored-by: Stefan Schüller Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller * Release 1.0.36 Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller Co-authored-by: lishoujun * Adding configuration setting and supporting code to pause playback on back button. (#167) Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller Co-authored-by: lishoujun Co-authored-by: Don Kimberlin * Making Selecting a search suggestion fill search field (#169) * Adding configuration setting and supporting code to choose language (#168) * Version Bump * Fixed merge issue * Server login (#175) * Release v1.0.38 Co-authored-by: Michael Moroni Co-authored-by: mostkai Co-authored-by: B0pol Co-authored-by: Jeannette L Co-authored-by: Nathan Co-authored-by: Mihail Iosilevitch Co-authored-by: anonymous Co-authored-by: Oymate Co-authored-by: Juanro49 Co-authored-by: Mostafa Ahangarha Co-authored-by: Szylu Co-authored-by: Artem Co-authored-by: jmgfr <13685004+jmgfr@users.noreply.github.com> Co-authored-by: Stefan Schueller Co-authored-by: lishoujun Co-authored-by: Allan Nordhøy Co-authored-by: Don Kimberlin --- CHANGELOG.md | 11 ++ app/build.gradle | 36 +++- app/src/main/AndroidManifest.xml | 22 +-- .../peertube/activity/AccountActivity.java | 8 +- .../activity/AppCompatPreferenceActivity.java | 19 ++ .../peertube/activity/MeActivity.java | 112 ++++++----- .../activity/SelectServerActivity.java | 40 ++-- .../activity/ServerAddressBookActivity.java | 168 +++++++++++++++++ .../peertube/activity/SettingsActivity.java | 23 +-- .../peertube/activity/VideoListActivity.java | 59 +++--- .../peertube/adapter/ServerAdapter.java | 22 ++- .../peertube/adapter/ServerListAdapter.java | 158 ++++++++++++++++ .../peertube/application/AppApplication.java | 17 ++ .../peertube/database/AppDatabase.java | 26 +++ .../schueller/peertube/database/Server.java | 87 +++++++++ .../peertube/database/ServerDao.java | 43 +++++ .../peertube/database/ServerRepository.java | 80 ++++++++ .../peertube/database/ServerRoomDatabase.java | 57 ++++++ .../peertube/database/ServerViewModel.java | 45 +++++ .../peertube/fragment/AddServerFragment.java | 178 ++++++++++++++++++ .../LoginService.java} | 120 +++--------- app/src/main/res/anim/slide_in_bottom.xml | 6 + app/src/main/res/anim/slide_out_bottom.xml | 6 + .../ic_baseline_account_circle_24.xml | 10 + .../main/res/drawable/ic_baseline_add_24.xml | 10 + .../res/drawable/ic_baseline_close_24.xml | 10 + .../main/res/drawable/ic_baseline_help_24.xml | 10 + .../drawable/ic_baseline_person_pin_24.xml | 10 + .../res/drawable/ic_baseline_settings_24.xml | 10 + .../drawable/ic_baseline_video_library_24.xml | 10 + app/src/main/res/layout/activity_login.xml | 113 ----------- app/src/main/res/layout/activity_me.xml | 149 ++++++++++++++- .../layout/activity_server_address_book.xml | 21 +++ .../res/layout/activity_server_selection.xml | 40 ---- .../layout/content_server_address_book.xml | 21 +++ .../main/res/layout/fragment_add_server.xml | 73 +++++++ app/src/main/res/layout/row_serverbook.xml | 51 +++++ app/src/main/res/menu/menu_top_account.xml | 5 - app/src/main/res/menu/menu_top_videolist.xml | 6 +- app/src/main/res/values-ar/strings.xml | 6 +- app/src/main/res/values-fr/strings.xml | 5 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 4 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/strings.xml | 36 +++- app/src/main/res/values/styles.xml | 49 +++-- app/src/main/res/xml/pref_general.xml | 3 - gradle/wrapper/gradle-wrapper.properties | 2 +- 49 files changed, 1566 insertions(+), 437 deletions(-) create mode 100644 app/src/main/java/net/schueller/peertube/activity/ServerAddressBookActivity.java create mode 100644 app/src/main/java/net/schueller/peertube/adapter/ServerListAdapter.java create mode 100644 app/src/main/java/net/schueller/peertube/database/AppDatabase.java create mode 100644 app/src/main/java/net/schueller/peertube/database/Server.java create mode 100644 app/src/main/java/net/schueller/peertube/database/ServerDao.java create mode 100644 app/src/main/java/net/schueller/peertube/database/ServerRepository.java create mode 100644 app/src/main/java/net/schueller/peertube/database/ServerRoomDatabase.java create mode 100644 app/src/main/java/net/schueller/peertube/database/ServerViewModel.java create mode 100644 app/src/main/java/net/schueller/peertube/fragment/AddServerFragment.java rename app/src/main/java/net/schueller/peertube/{activity/LoginActivity.java => service/LoginService.java} (50%) create mode 100644 app/src/main/res/anim/slide_in_bottom.xml create mode 100644 app/src/main/res/anim/slide_out_bottom.xml create mode 100644 app/src/main/res/drawable/ic_baseline_account_circle_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_add_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_close_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_help_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_person_pin_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_settings_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_video_library_24.xml delete mode 100644 app/src/main/res/layout/activity_login.xml create mode 100644 app/src/main/res/layout/activity_server_address_book.xml create mode 100644 app/src/main/res/layout/content_server_address_book.xml create mode 100644 app/src/main/res/layout/fragment_add_server.xml create mode 100644 app/src/main/res/layout/row_serverbook.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 890a691..1c6ebb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### Version 1.0.38 Tag: v1.0.8 (2020-06-21) + * Multi server login address book + * Clear search history (@dhk2) + * Android SDK to 29 + * Various translations + ### Version 1.0.37 Tag: v1.0.37 (2020-06-19) * Making Selecting a search suggestion fill search field (@dhk2) * Adding configuration setting and supporting code to choose language (@dhk2) @@ -23,6 +29,11 @@ * Gradle update * Translations +### Version 1.0.31 Tag: v1.0.31 (2019-09-25) +* Renamed overview to discover (PeerTube v1.4.0) +* Translations +* Gradle dependencies updates + ### Version 1.0.30 Tag: v1.0.30 (2019-08-07) * Gradle update * Translations diff --git a/app/build.gradle b/app/build.gradle index fdc4ca7..2e7865f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,19 +1,27 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "net.schueller.peertube" minSdkVersion 21 - targetSdkVersion 28 - versionCode 1037 - versionName "1.0.37" + targetSdkVersion 29 + versionCode 1038 + versionName "1.0.38" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ext { libVersions = [ exoplayer: '2.9.3' ] } + javaCompileOptions { + annotationProcessorOptions { + arguments = [ + "room.schemaLocation" : "$projectDir/schemas".toString(), + "room.incremental" : "true", + "room.expandProjection": "true"] + } + } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) @@ -70,7 +78,6 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - buildToolsVersion '28.0.3' applicationVariants.all { variant -> variant.resValue "string", "versionName", variant.versionName @@ -78,6 +85,23 @@ android { } dependencies { - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta6' + def room_version = "2.2.5" + def archLifecycleVersion = '2.1.0' + + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7' implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.1.0' + + // database lib + implementation "androidx.room:room-runtime:$room_version" + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + annotationProcessor "androidx.room:room-compiler:$room_version" + androidTestImplementation "androidx.room:room-testing:$room_version" + + // Lifecycle components + implementation "androidx.lifecycle:lifecycle-extensions:$archLifecycleVersion" + annotationProcessor "androidx.lifecycle:lifecycle-common-java8:$archLifecycleVersion" + } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5250d9f..11f705c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,11 +2,7 @@ - - - - - + + + android:resource="@xml/searchable" /> - - + + + + + \ No newline at end of file diff --git a/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java b/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java index 4c4b5cf..d80b58c 100644 --- a/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java @@ -48,6 +48,7 @@ import net.schueller.peertube.network.RetrofitInstance; import java.util.ArrayList; +import java.util.Objects; import java.util.Set; import androidx.annotation.NonNull; @@ -145,11 +146,10 @@ public class AccountActivity extends CommonActivity { Toolbar toolbar = findViewById(R.id.tool_bar_account); // Setting toolbar as the ActionBar with setSupportActionBar() call setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_baseline_close_24); getSupportActionBar().setTitle(displayNameAndHost); - getSupportActionBar().setHomeAsUpIndicator( - new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar() - ); loadAccountVideos(displayNameAndHost); diff --git a/app/src/main/java/net/schueller/peertube/activity/AppCompatPreferenceActivity.java b/app/src/main/java/net/schueller/peertube/activity/AppCompatPreferenceActivity.java index b2d9461..36d5fe0 100644 --- a/app/src/main/java/net/schueller/peertube/activity/AppCompatPreferenceActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/AppCompatPreferenceActivity.java @@ -18,6 +18,7 @@ package net.schueller.peertube.activity; +import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; import android.preference.PreferenceActivity; @@ -25,10 +26,14 @@ import androidx.annotation.LayoutRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatDelegate; +import android.preference.PreferenceManager; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; +import static net.schueller.peertube.helper.Constants.DEFAULT_THEME; +import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY; + /** * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls * to be used with AppCompat. @@ -42,6 +47,20 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity { getDelegate().installViewFactory(); getDelegate().onCreate(savedInstanceState); super.onCreate(savedInstanceState); + + // TODO: cleanup this duplication + + // Set Night Mode + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + AppCompatDelegate.setDefaultNightMode(sharedPref.getBoolean("pref_dark_mode", false) ? + AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO); + + // Set theme + setTheme(getResources().getIdentifier( + sharedPref.getString(THEME_PREF_KEY, DEFAULT_THEME), + "style", + getPackageName()) + ); } @Override diff --git a/app/src/main/java/net/schueller/peertube/activity/MeActivity.java b/app/src/main/java/net/schueller/peertube/activity/MeActivity.java index 4153d74..572bb68 100644 --- a/app/src/main/java/net/schueller/peertube/activity/MeActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/MeActivity.java @@ -19,18 +19,20 @@ package net.schueller.peertube.activity; import android.content.Intent; +import android.net.Uri; +import android.nfc.Tag; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; -import android.view.MenuItem; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; -import com.mikepenz.fontawesome_typeface_library.FontAwesome; -import com.mikepenz.iconics.IconicsDrawable; - import net.schueller.peertube.R; import net.schueller.peertube.helper.APIUrlHelper; +import net.schueller.peertube.model.Avatar; import net.schueller.peertube.model.Me; import net.schueller.peertube.network.GetUserService; import net.schueller.peertube.network.RetrofitInstance; @@ -38,10 +40,17 @@ import net.schueller.peertube.network.Session; import androidx.annotation.NonNull; import androidx.appcompat.widget.Toolbar; + +import com.squareup.picasso.Picasso; + +import java.util.Objects; + import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; +import static net.schueller.peertube.application.AppApplication.getContext; + public class MeActivity extends CommonActivity { @@ -52,34 +61,10 @@ public class MeActivity extends CommonActivity { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_top_account, menu); - // Set an icon in the ActionBar - menu.findItem(R.id.action_logout).setIcon( - new IconicsDrawable(this, FontAwesome.Icon.faw_sign_out_alt).actionBar()); - return true; } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - // action with ID action_refresh was selected - - case R.id.action_logout: - Session.getInstance().invalidate(); - Intent intent = new Intent(this, LoginActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - this.startActivity(intent); - finish(); - return true; - default: - break; - } - - return super.onOptionsItemSelected(item); - } - @Override public boolean onSupportNavigateUp() { finish(); // close this activity as oppose to navigating up @@ -97,66 +82,99 @@ public class MeActivity extends CommonActivity { Toolbar toolbar = findViewById(R.id.tool_bar_me); // Setting toolbar as the ActionBar with setSupportActionBar() call setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeAsUpIndicator( - new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar() - ); + Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_baseline_close_24); + + LinearLayout account = findViewById(R.id.a_me_account_line); + LinearLayout settings = findViewById(R.id.a_me_settings); + LinearLayout help = findViewById(R.id.a_me_helpnfeedback); + + TextView logout = findViewById(R.id.a_me_logout); - init(); - } + settings.setOnClickListener(view -> { + Intent settingsActivity = new Intent(getContext(), SettingsActivity.class); + //overridePendingTransition(R.anim.slide_in_bottom, 0); + startActivity(settingsActivity); + }); + + help.setOnClickListener(view -> { + String url = "https://github.com/sschueller/peertube-android/issues"; + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(url)); + startActivity(i); + }); + + logout.setOnClickListener(view -> { + Session.getInstance().invalidate(); + account.setVisibility(View.GONE); + + }); - private void init() { - // try to get user data getUserData(); } - private boolean getUserData() { - - // TODO + private void getUserData() { String apiBaseURL = APIUrlHelper.getUrlWithVersion(this); + String baseURL = APIUrlHelper.getUrl(this); GetUserService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class); Call call = service.getMe(); call.enqueue(new Callback() { + + LinearLayout account = findViewById(R.id.a_me_account_line); + @Override public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { Me me = response.body(); - TextView username = findViewById(R.id.account_username); - TextView email = findViewById(R.id.account_email); + Log.d(TAG, response.body().toString()); + + TextView username = findViewById(R.id.a_me_username); + TextView email = findViewById(R.id.a_me_email); + ImageView avatarView = findViewById(R.id.a_me_avatar); + username.setText(me.getUsername()); email.setText(me.getEmail()); - Log.v(TAG, me.getEmail()); + Avatar avatar = me.getAccount().getAvatar(); + if (avatar != null) { + String avatarPath = avatar.getPath(); + Picasso.get() + .load(baseURL + avatarPath) + .into(avatarView); + } + account.setVisibility(View.VISIBLE); + + } else { + account.setVisibility(View.GONE); } - } @Override - public void onFailure(Call call, Throwable t) { - + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + account.setVisibility(View.GONE); } }); - return true; } @Override protected void onResume() { super.onResume(); - init(); + getUserData(); } } diff --git a/app/src/main/java/net/schueller/peertube/activity/SelectServerActivity.java b/app/src/main/java/net/schueller/peertube/activity/SelectServerActivity.java index b2da65f..26d56f2 100644 --- a/app/src/main/java/net/schueller/peertube/activity/SelectServerActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/SelectServerActivity.java @@ -1,3 +1,20 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package net.schueller.peertube.activity; import androidx.annotation.NonNull; @@ -9,6 +26,7 @@ import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; +import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; @@ -54,28 +72,6 @@ public class SelectServerActivity extends AppCompatActivity { loadList(); - // set url - TextView selectedUrl = findViewById(R.id.serverSelectedUrl); - selectedUrl.setText(APIUrlHelper.getUrl(SelectServerActivity.this)); - - Button setServerButton = findViewById(R.id.server_selection_set); - setServerButton.setOnClickListener(v -> { - - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); - SharedPreferences.Editor editor = sharedPref.edit(); - - String serverUrl = APIUrlHelper.cleanServerUrl(selectedUrl.getText().toString()); - - if (!Patterns.WEB_URL.matcher(serverUrl).matches()) { - Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_LONG).show(); - } else { - editor.putString("pref_api_base", serverUrl); - editor.apply(); - this.finish(); - } - - }); - } diff --git a/app/src/main/java/net/schueller/peertube/activity/ServerAddressBookActivity.java b/app/src/main/java/net/schueller/peertube/activity/ServerAddressBookActivity.java new file mode 100644 index 0000000..cedc664 --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/activity/ServerAddressBookActivity.java @@ -0,0 +1,168 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.activity; + +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import net.schueller.peertube.R; +import net.schueller.peertube.adapter.ServerListAdapter; +import net.schueller.peertube.database.Server; +import net.schueller.peertube.database.ServerViewModel; +import net.schueller.peertube.fragment.AddServerFragment; + +import java.util.List; + + +public class ServerAddressBookActivity extends CommonActivity implements AddServerFragment.OnFragmentInteractionListener { + + private String TAG = "ServerAddressBookActivity"; + public static final String EXTRA_REPLY = "net.schueller.peertube.room.REPLY"; + + private ServerViewModel mServerViewModel; + private AddServerFragment addServerFragment; + private FloatingActionButton floatingActionButton; + private FragmentManager fragmentManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_server_address_book); + + + mServerViewModel = new ViewModelProvider(this).get(ServerViewModel.class); + + showServers(); + + floatingActionButton = findViewById(R.id.add_server); + floatingActionButton.setOnClickListener(view -> { + + Log.d(TAG, "Click"); + + fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + addServerFragment = new AddServerFragment(); + fragmentTransaction.replace(R.id.server_book, addServerFragment); + fragmentTransaction.commit(); + + floatingActionButton.hide(); + + }); + + } + + @Override + public void onFragmentInteraction(Uri uri) { + + } + + @Override + public void onPointerCaptureChanged(boolean hasCapture) { + + } + + + public void showServers() + { + RecyclerView recyclerView = findViewById(R.id.server_list_recyclerview); + final ServerListAdapter adapter = new ServerListAdapter(this); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + + // Delete items on swipe + ItemTouchHelper helper = new ItemTouchHelper( + new ItemTouchHelper.SimpleCallback(0, + ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, + int direction) { + int position = viewHolder.getAdapterPosition(); + Server server = adapter.getServerAtPosition(position); + Toast.makeText(ServerAddressBookActivity.this, "Deleting " + + server.getServerName(), Toast.LENGTH_LONG).show(); + + // Delete the server + mServerViewModel.delete(server); + } + }); + helper.attachToRecyclerView(recyclerView); + + + // Update the cached copy of the words in the adapter. + mServerViewModel.getAllServers().observe(this, adapter::setServers); + + } + + public void addServer(View view) + { + Log.d(TAG, "addServer"); + + EditText serverLabel = view.findViewById(R.id.serverLabel); + EditText serverUrl = view.findViewById(R.id.serverUrl); + EditText serverUsername = view.findViewById(R.id.serverUsername); + EditText serverPassword = view.findViewById(R.id.serverPassword); + + Server server = new Server(serverLabel.getText().toString()); + + server.setServerHost(serverUrl.getText().toString()); + server.setUsername(serverUsername.getText().toString()); + server.setPassword(serverPassword.getText().toString()); + + mServerViewModel.insert(server); + + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.remove(addServerFragment); + fragmentTransaction.commit(); + + floatingActionButton.show(); + + } + + public void testServer() + { + + } + +} diff --git a/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java b/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java index 2179de4..c8be62b 100644 --- a/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java @@ -135,13 +135,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { - // Set theme - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); - setTheme(getResources().getIdentifier( - sharedPref.getString(THEME_PREF_KEY, DEFAULT_THEME), - "style", - getPackageName()) - ); super.onCreate(savedInstanceState); @@ -202,7 +195,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { // to their values. When their values change, their summaries are // updated to reflect the new value, per the Android Design // guidelines. - bindPreferenceSummaryToValue(findPreference("pref_api_base")); + //bindPreferenceSummaryToValue(findPreference("pref_api_base")); bindPreferenceSummaryToValue(findPreference("pref_theme")); } @@ -219,12 +212,12 @@ public class SettingsActivity extends AppCompatPreferenceActivity { @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { - String key = preference.getKey(); - if ("pref_api_base".equals(key)) { - Intent intentServer = new Intent(preference.getContext(), SelectServerActivity.class); - startActivity(intentServer); - return true; - } +// String key = preference.getKey(); +// if ("pref_api_base".equals(key)) { +// Intent intentServer = new Intent(preference.getContext(), SelectServerActivity.class); +// startActivity(intentServer); +// return true; +// } return false; } @@ -232,7 +225,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { public void onResume() { setPreferenceScreen(null); addPreferencesFromResource(R.xml.pref_general); - bindPreferenceSummaryToValue(findPreference("pref_api_base")); + //bindPreferenceSummaryToValue(findPreference("pref_api_base")); super.onResume(); } diff --git a/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java b/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java index 107a200..c4ca315 100644 --- a/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java @@ -50,6 +50,7 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; +import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; @@ -81,6 +82,7 @@ public class VideoListActivity extends CommonActivity { public static final String EXTRA_VIDEOID = "VIDEOID"; public static final String EXTRA_ACCOUNTDISPLAYNAME = "ACCOUNTDISPLAYNAMEANDHOST"; + public static final Integer SWITCH_INSTANCE = 2; private VideoAdapter videoAdapter; private SwipeRefreshLayout swipeRefreshLayout; @@ -125,14 +127,11 @@ public class VideoListActivity extends CommonActivity { inflater.inflate(R.menu.menu_top_videolist, menu); // Set an icon in the ActionBar - menu.findItem(R.id.action_settings).setIcon( - new IconicsDrawable(this, FontAwesome.Icon.faw_cog).actionBar()); - menu.findItem(R.id.action_account).setIcon( new IconicsDrawable(this, FontAwesome.Icon.faw_user_circle).actionBar()); -// menu.findItem(R.id.action_server_selection).setIcon( -// new IconicsDrawable(this, FontAwesome.Icon.faw_server).actionBar()); + menu.findItem(R.id.action_server_address_book).setIcon( + new IconicsDrawable(this, FontAwesome.Icon.faw_server).actionBar()); MenuItem searchMenuItem = menu.findItem(R.id.action_search); @@ -219,6 +218,16 @@ public class VideoListActivity extends CommonActivity { stopService(new Intent(this, VideoPlayerService.class)); } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == SWITCH_INSTANCE) { + if(resultCode == RESULT_OK) { + loadVideos(currentStart, count, sort, filter); + } + } + } + @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will @@ -231,25 +240,28 @@ public class VideoListActivity extends CommonActivity { //Toast.makeText(this, "Search Selected", Toast.LENGTH_SHORT).show(); return false; - case R.id.action_settings: -// Toast.makeText(this, "Login Selected", Toast.LENGTH_SHORT).show(); - Intent intentSettings = new Intent(this, SettingsActivity.class); - this.startActivity(intentSettings); - - return true; case R.id.action_account: - if (!Session.getInstance().isLoggedIn()) { - Intent intentLogin = new Intent(this, LoginActivity.class); - this.startActivity(intentLogin); - } else { +// if (!Session.getInstance().isLoggedIn()) { + + //Intent intentLogin = new Intent(this, ServerAddressBookActivity.class); + Intent intentMe = new Intent(this, MeActivity.class); this.startActivity(intentMe); - } + + //overridePendingTransition(R.anim.slide_in_bottom, 0); + + + // this.startActivity(intentLogin); + +// } else { +// Intent intentMe = new Intent(this, MeActivity.class); +// this.startActivity(intentMe); +// } + return false; + case R.id.action_server_address_book: + Intent addressBookActivityIntent = new Intent(this, ServerAddressBookActivity.class); + this.startActivityForResult(addressBookActivityIntent, SWITCH_INSTANCE); return false; -// case R.id.action_server_selection: -// Intent intentServer = new Intent(this, SelectServerActivity.class); -// this.startActivity(intentServer); -// return false; default: break; } @@ -378,6 +390,7 @@ public class VideoListActivity extends CommonActivity { @Override protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); setIntent(intent); handleIntent(intent); } @@ -483,8 +496,10 @@ public class VideoListActivity extends CommonActivity { //Log.v(TAG, "navigation_subscriptions"); if (!Session.getInstance().isLoggedIn()) { - Intent intent = new Intent(this, LoginActivity.class); - this.startActivity(intent); +// Intent intent = new Intent(this, LoginActivity.class); +// this.startActivity(intent); + Intent addressBookActivityIntent = new Intent(this, ServerAddressBookActivity.class); + this.startActivityForResult(addressBookActivityIntent, SWITCH_INSTANCE); return false; } else { diff --git a/app/src/main/java/net/schueller/peertube/adapter/ServerAdapter.java b/app/src/main/java/net/schueller/peertube/adapter/ServerAdapter.java index 0e3de08..7bde807 100644 --- a/app/src/main/java/net/schueller/peertube/adapter/ServerAdapter.java +++ b/app/src/main/java/net/schueller/peertube/adapter/ServerAdapter.java @@ -18,6 +18,7 @@ package net.schueller.peertube.adapter; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.view.LayoutInflater; @@ -37,6 +38,8 @@ import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; +import static android.app.Activity.RESULT_OK; + public class ServerAdapter extends RecyclerView.Adapter { @@ -75,18 +78,25 @@ public class ServerAdapter extends RecyclerView.Adapter { - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(activity); - SharedPreferences.Editor editor = sharedPref.edit(); +// SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(activity); +// SharedPreferences.Editor editor = sharedPref.edit(); String serverUrl = APIUrlHelper.cleanServerUrl(serverList.get(position).getHost()); - editor.putString("pref_api_base", serverUrl); - editor.apply(); - - activity.finish(); +// editor.putString("pref_api_base", serverUrl); +// editor.apply(); +// +// Toast.makeText(activity, activity.getString(R.string.server_selection_set_server, serverUrl), Toast.LENGTH_LONG).show(); + Intent intent = new Intent(); + intent.putExtra("serverUrl", serverUrl); + intent.putExtra("serverName", serverList.get(position).getName()); + activity.setResult(RESULT_OK, intent); + + activity.finish(); + }); // diff --git a/app/src/main/java/net/schueller/peertube/adapter/ServerListAdapter.java b/app/src/main/java/net/schueller/peertube/adapter/ServerListAdapter.java new file mode 100644 index 0000000..f7225df --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/adapter/ServerListAdapter.java @@ -0,0 +1,158 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.adapter; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.provider.SearchRecentSuggestions; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import net.schueller.peertube.R; + +import net.schueller.peertube.activity.SelectServerActivity; +import net.schueller.peertube.activity.ServerAddressBookActivity; +import net.schueller.peertube.activity.VideoListActivity; +import net.schueller.peertube.database.Server; +import net.schueller.peertube.helper.APIUrlHelper; +import net.schueller.peertube.provider.SearchSuggestionsProvider; +import net.schueller.peertube.service.LoginService; + + +import java.util.List; + +import static android.app.Activity.RESULT_OK; + +public class ServerListAdapter extends RecyclerView.Adapter { + + + private final LayoutInflater mInflater; + private List mServers; // Cached copy of Servers + + public ServerListAdapter(Context context) { + this.mInflater = LayoutInflater.from(context); + } + + @NonNull + @Override + public ServerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View itemView = mInflater.inflate(R.layout.row_serverbook, parent, false); + return new ServerViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull ServerViewHolder holder, int position) { + + if (mServers != null) { + Server current = mServers.get(position); + holder.serverLabel.setText(current.getServerName()); + holder.serverUrl.setText(current.getServerHost()); + + if (TextUtils.isEmpty(current.getUsername())) { + holder.hasLogin.setVisibility(View.GONE); + } else { + holder.hasLogin.setVisibility(View.VISIBLE); + } + + } else { + // Covers the case of data not being ready yet. + holder.serverLabel.setText(R.string.server_book_no_servers_found); + } + + holder.itemView.setOnClickListener(v -> { + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mInflater.getContext()); + SharedPreferences.Editor editor = sharedPref.edit(); + + String serverUrl = APIUrlHelper.cleanServerUrl(getServerAtPosition(position).getServerHost()); + + editor.putString("pref_api_base", serverUrl); + editor.apply(); + + // attempt authentication if we have a username + if (!TextUtils.isEmpty(getServerAtPosition(position).getUsername())) { + LoginService.Authenticate( + getServerAtPosition(position).getUsername(), + getServerAtPosition(position).getPassword() + ); + } + + // tell server list activity to reload list + Intent intent = new Intent(); + ((Activity) mInflater.getContext()).setResult(RESULT_OK, intent); + + // close this activity + ((Activity) mInflater.getContext()).finish(); + + Toast.makeText(mInflater.getContext(), mInflater.getContext().getString(R.string.server_selection_set_server, serverUrl), Toast.LENGTH_LONG).show(); + + }); + + +// +// holder.itemView.setOnLongClickListener(v -> { +// Log.v("ServerListAdapter", "setOnLongClickListener " + position); +// return true; +// }); + + + } + + public void setServers(List Servers) { + mServers = Servers; + this.notifyDataSetChanged(); + } + + // getItemCount() is called many times, and when it is first called, + // mServers has not been updated (means initially, it's null, and we can't return null). + @Override + public int getItemCount() { + if (mServers != null) + return mServers.size(); + else return 0; + } + + static class ServerViewHolder extends RecyclerView.ViewHolder { + TextView serverLabel, serverUrl, serverUsername; + ImageView hasLogin; + + private ServerViewHolder(View itemView) { + super(itemView); + serverLabel = itemView.findViewById(R.id.serverLabelRow); + serverUrl = itemView.findViewById(R.id.serverUrlRow); + hasLogin = itemView.findViewById(R.id.sb_row_has_login_icon); + } + } + + public Server getServerAtPosition (int position) { + return mServers.get(position); + } +} \ No newline at end of file diff --git a/app/src/main/java/net/schueller/peertube/application/AppApplication.java b/app/src/main/java/net/schueller/peertube/application/AppApplication.java index 05869b4..98f0996 100644 --- a/app/src/main/java/net/schueller/peertube/application/AppApplication.java +++ b/app/src/main/java/net/schueller/peertube/application/AppApplication.java @@ -1,3 +1,20 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package net.schueller.peertube.application; import android.app.Application; diff --git a/app/src/main/java/net/schueller/peertube/database/AppDatabase.java b/app/src/main/java/net/schueller/peertube/database/AppDatabase.java new file mode 100644 index 0000000..bc1643e --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/database/AppDatabase.java @@ -0,0 +1,26 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.database; + +import androidx.room.Database; +import androidx.room.RoomDatabase; + +@Database(entities = {Server.class}, version = 1) +public abstract class AppDatabase extends RoomDatabase { + public abstract ServerDao serverDao(); +} \ No newline at end of file diff --git a/app/src/main/java/net/schueller/peertube/database/Server.java b/app/src/main/java/net/schueller/peertube/database/Server.java new file mode 100644 index 0000000..5c0f7e1 --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/database/Server.java @@ -0,0 +1,87 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.database; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.PrimaryKey; + +@Entity(tableName = "server_table") +public class Server { + + @PrimaryKey(autoGenerate = true) + private int id; + + @NonNull + @ColumnInfo(name = "server_name") + private String serverName; + + @ColumnInfo(name = "server_host") + private String serverHost; + + @ColumnInfo(name = "username") + private String username; + + @ColumnInfo(name = "password") + private String password; + + public Server(@NonNull String serverName) { + this.serverName = serverName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public String getServerHost() { + return serverHost; + } + + public void setServerHost(String serverHost) { + this.serverHost = serverHost; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/app/src/main/java/net/schueller/peertube/database/ServerDao.java b/app/src/main/java/net/schueller/peertube/database/ServerDao.java new file mode 100644 index 0000000..e01ef5f --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/database/ServerDao.java @@ -0,0 +1,43 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.database; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Delete; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import java.util.List; + +@Dao +public interface ServerDao { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(Server server); + + @Query("DELETE FROM server_table") + void deleteAll(); + + @Delete + void delete(Server server); + + @Query("SELECT * from server_table ORDER BY server_name DESC") + LiveData> getAllServers(); +} \ No newline at end of file diff --git a/app/src/main/java/net/schueller/peertube/database/ServerRepository.java b/app/src/main/java/net/schueller/peertube/database/ServerRepository.java new file mode 100644 index 0000000..001cb7c --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/database/ServerRepository.java @@ -0,0 +1,80 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.database; + +import android.app.Application; +import android.os.AsyncTask; + + +import androidx.lifecycle.LiveData; + +import java.util.List; + +class ServerRepository { + + private ServerDao mServerDao; + private LiveData> mAllServers; + + ServerRepository(Application application) { + ServerRoomDatabase db = ServerRoomDatabase.getDatabase(application); + mServerDao = db.serverDao(); + mAllServers = mServerDao.getAllServers(); + + } + + LiveData> getAllServers() { + return mAllServers; + } + + void insert (Server server) { + new insertAsyncTask(mServerDao).execute(server); + } + + public void delete(Server server) { + new deleteServerAsyncTask(mServerDao).execute(server); + } + + private static class insertAsyncTask extends AsyncTask { + + private ServerDao mAsyncTaskDao; + + insertAsyncTask(ServerDao dao) { + mAsyncTaskDao = dao; + } + + @Override + protected Void doInBackground(final Server... params) { + mAsyncTaskDao.insert(params[0]); + return null; + } + } + + private static class deleteServerAsyncTask extends AsyncTask { + private ServerDao mAsyncTaskDao; + + deleteServerAsyncTask(ServerDao dao) { + mAsyncTaskDao = dao; + } + + @Override + protected Void doInBackground(final Server... params) { + mAsyncTaskDao.delete(params[0]); + return null; + } + } +} diff --git a/app/src/main/java/net/schueller/peertube/database/ServerRoomDatabase.java b/app/src/main/java/net/schueller/peertube/database/ServerRoomDatabase.java new file mode 100644 index 0000000..deb79a2 --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/database/ServerRoomDatabase.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.database; + +import android.content.Context; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Database(entities = {Server.class}, version = 1, exportSchema = false) +public abstract class ServerRoomDatabase extends RoomDatabase { + + public abstract ServerDao serverDao(); + + private static volatile ServerRoomDatabase INSTANCE; + + private static final int NUMBER_OF_THREADS = 4; + + static final ExecutorService databaseWriteExecutor = + Executors.newFixedThreadPool(NUMBER_OF_THREADS); + + public static ServerRoomDatabase getDatabase(final Context context) { + if (INSTANCE == null) { + synchronized (ServerRoomDatabase.class) { + if (INSTANCE == null) { + if (INSTANCE == null) { + INSTANCE = Room.databaseBuilder(context.getApplicationContext(), + ServerRoomDatabase.class, "server_database") + .build(); + } + } + } + } + return INSTANCE; + } + +} + diff --git a/app/src/main/java/net/schueller/peertube/database/ServerViewModel.java b/app/src/main/java/net/schueller/peertube/database/ServerViewModel.java new file mode 100644 index 0000000..bdd9b1c --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/database/ServerViewModel.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.database; + +import android.app.Application; + +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; + +import java.util.List; + +public class ServerViewModel extends AndroidViewModel { + + private ServerRepository mRepository; + + private LiveData> mAllServers; + + public ServerViewModel (Application application) { + super(application); + mRepository = new ServerRepository(application); + mAllServers = mRepository.getAllServers(); + } + + public LiveData> getAllServers() { return mAllServers; } + + public void insert(Server server) { mRepository.insert(server); } + + public void delete(Server server) {mRepository.delete(server);} + +} diff --git a/app/src/main/java/net/schueller/peertube/fragment/AddServerFragment.java b/app/src/main/java/net/schueller/peertube/fragment/AddServerFragment.java new file mode 100644 index 0000000..6e15a2b --- /dev/null +++ b/app/src/main/java/net/schueller/peertube/fragment/AddServerFragment.java @@ -0,0 +1,178 @@ +/* + * Copyright 2018 Stefan Schüller + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.schueller.peertube.fragment; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import android.text.TextUtils; +import android.util.Log; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import net.schueller.peertube.R; +import net.schueller.peertube.activity.SelectServerActivity; +import net.schueller.peertube.activity.ServerAddressBookActivity; +import net.schueller.peertube.helper.APIUrlHelper; + +import static android.app.Activity.RESULT_OK; + + +public class AddServerFragment extends Fragment { + + public static final String TAG = "AddServerFragment"; + public static final Integer PICK_SERVER = 1; + + private OnFragmentInteractionListener mListener; + + private View mView; + + public AddServerFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + Log.d(TAG, "onCreateView"); + // Inflate the layout for this fragment + + mView = inflater.inflate(R.layout.fragment_add_server, container, false); + + // bind button click + Button addServerButton = mView.findViewById(R.id.addServerButton); + addServerButton.setOnClickListener(view -> { + + Activity act = getActivity(); + + Boolean formValid = true; + + // close keyboard + try { + InputMethodManager inputManager = (InputMethodManager) + act.getSystemService(Context.INPUT_METHOD_SERVICE); + + inputManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), + InputMethodManager.HIDE_NOT_ALWAYS); + } catch (Exception e) { + + } + + EditText selectedLabel = mView.findViewById(R.id.serverLabel); + if ( TextUtils.isEmpty(selectedLabel.getText())){ + selectedLabel.setError( act.getString(R.string.server_book_label_is_required )); + Toast.makeText(act, R.string.invalid_url, Toast.LENGTH_LONG).show(); + formValid = false; + } + + // validate url + EditText selectedUrl = mView.findViewById(R.id.serverUrl); + String serverUrl = APIUrlHelper.cleanServerUrl(selectedUrl.getText().toString()); + selectedUrl.setText(serverUrl); + + if (!Patterns.WEB_URL.matcher(serverUrl).matches()) { + selectedUrl.setError( act.getString(R.string.server_book_valid_url_is_required ) ); + Toast.makeText(act, R.string.invalid_url, Toast.LENGTH_LONG).show(); + formValid = false; + } + + if (formValid) { + if (act instanceof ServerAddressBookActivity) { + ((ServerAddressBookActivity) act).addServer(mView); + + } + } + + }); + +// Button testServerButton = mView.findViewById(R.id.testServerButton); +// testServerButton.setOnClickListener(view -> { +// Activity act = getActivity(); +// if (act instanceof ServerAddressBookActivity) { +// ((ServerAddressBookActivity) act).testServer(); +// } +// }); + + Button pickServerUrl = mView.findViewById(R.id.pickServerUrl); + pickServerUrl.setOnClickListener(view -> { + Intent intentServer = new Intent(getActivity(), SelectServerActivity.class); + this.startActivityForResult(intentServer, PICK_SERVER); + }); + + return mView; + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PICK_SERVER) { + if(resultCode == RESULT_OK) { + + String serverUrlTest = data.getStringExtra("serverUrl"); + //Log.d(TAG, "serverUrl " + serverUrlTest); + EditText serverUrl = mView.findViewById(R.id.serverUrl); + serverUrl.setText(serverUrlTest); + + EditText serverLabel = mView.findViewById(R.id.serverLabel); + if ("".equals(serverLabel.getText().toString())) { + serverLabel.setText(data.getStringExtra("serverName")); + } + + } + } + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + public interface OnFragmentInteractionListener { + // TODO: Update argument type and name + void onFragmentInteraction(Uri uri); + } +} diff --git a/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java b/app/src/main/java/net/schueller/peertube/service/LoginService.java similarity index 50% rename from app/src/main/java/net/schueller/peertube/activity/LoginActivity.java rename to app/src/main/java/net/schueller/peertube/service/LoginService.java index df0a6df..6891c92 100644 --- a/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java +++ b/app/src/main/java/net/schueller/peertube/service/LoginService.java @@ -15,23 +15,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - -package net.schueller.peertube.activity; +package net.schueller.peertube.service; import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import android.os.Bundle; -import android.text.InputType; import android.util.Log; -import android.widget.AutoCompleteTextView; -import android.widget.Button; -import android.widget.EditText; import android.widget.Toast; -import com.mikepenz.fontawesome_typeface_library.FontAwesome; -import com.mikepenz.iconics.IconicsDrawable; +import androidx.annotation.NonNull; import net.schueller.peertube.R; import net.schueller.peertube.helper.APIUrlHelper; @@ -40,88 +32,23 @@ import net.schueller.peertube.model.Token; import net.schueller.peertube.network.AuthenticationService; import net.schueller.peertube.network.RetrofitInstance; -import androidx.annotation.NonNull; -import androidx.appcompat.widget.Toolbar; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; -public class LoginActivity extends CommonActivity { +import static net.schueller.peertube.application.AppApplication.getContext; - private String TAG = "LoginActivity"; +public class LoginService { - // UI references. - private AutoCompleteTextView mEmailView; - private EditText mPasswordView; + private static final String TAG = "LoginService"; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public static void Authenticate(String username, String password) + { + Context context = getContext(); - setContentView(R.layout.activity_login); + String apiBaseURL = APIUrlHelper.getUrlWithVersion(context); - // bind button click - Button mEmailSignInButton = findViewById(R.id.email_sign_in_button); - mEmailSignInButton.setOnClickListener(view -> attemptLogin()); - - mEmailView = findViewById(R.id.email); - mPasswordView = findViewById(R.id.password); - - - // Attaching the layout to the toolbar object - Toolbar toolbar = findViewById(R.id.tool_bar_login); - // Setting toolbar as the ActionBar with setSupportActionBar() call - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeAsUpIndicator( - new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar() - ); - - } - - @Override - public void onResume() { - - EditText mServerName = findViewById(R.id.login_current_server); - mServerName.setText(APIUrlHelper.getUrl(this)); - mServerName.setInputType(InputType.TYPE_NULL); - - super.onResume(); - } - - @Override - public boolean onSupportNavigateUp() { - finish(); // close this activity as oppose to navigating up - - return false; - } - - private void attemptLogin() { - - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); - - Context context = this; - - // Reset errors. - mEmailView.setError(null); - mPasswordView.setError(null); - - // Store values at the time of the login attempt. - String email = mEmailView.getText().toString(); - String password = mPasswordView.getText().toString(); - - //check values - if (email.isEmpty()) { - Toast.makeText(LoginActivity.this, "Email/Username is empty", Toast.LENGTH_LONG).show(); - return; - } - if (password.isEmpty()) { - Toast.makeText(LoginActivity.this, "Password is empty", Toast.LENGTH_LONG).show(); - return; - } - // make http call to login and save access tokens - - String apiBaseURL = APIUrlHelper.getUrlWithVersion(this); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); AuthenticationService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(AuthenticationService.class); @@ -141,7 +68,7 @@ public class LoginActivity extends CommonActivity { "code", "password", "upload", - email, + username, password ); call2.enqueue(new Callback() { @@ -157,23 +84,19 @@ public class LoginActivity extends CommonActivity { // TODO: calc expiration //editor.putInt(getString(R.string.pref_token_expiration), token.getRefreshToken()); - editor.putString(getString(R.string.pref_token_access), token.getAccessToken()); - editor.putString(getString(R.string.pref_token_refresh), token.getExpiresIn()); - editor.putString(getString(R.string.pref_token_type), token.getTokenType()); - editor.commit(); + editor.putString(context.getString(R.string.pref_token_access), token.getAccessToken()); + editor.putString(context.getString(R.string.pref_token_refresh), token.getExpiresIn()); + editor.putString(context.getString(R.string.pref_token_type), token.getTokenType()); + editor.apply(); Log.wtf(TAG, "Logged in"); - Intent intent = new Intent(context, MeActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - context.startActivity(intent); + Toast.makeText(context, context.getString(R.string.authentication_login_success), Toast.LENGTH_LONG).show(); - finish(); // close this activity } else { Log.wtf(TAG, response2.toString()); - - Toast.makeText(LoginActivity.this, "Login Error!", Toast.LENGTH_LONG).show(); + Toast.makeText(context, context.getString(R.string.authentication_login_failed), Toast.LENGTH_LONG).show(); } } @@ -181,21 +104,24 @@ public class LoginActivity extends CommonActivity { @Override public void onFailure(@NonNull Call call2, @NonNull Throwable t2) { Log.wtf("err", t2.fillInStackTrace()); + Toast.makeText(context, context.getString(R.string.authentication_login_failed), Toast.LENGTH_LONG).show(); + } }); } else { Log.wtf(TAG, response.toString()); + Toast.makeText(context, context.getString(R.string.authentication_login_failed), Toast.LENGTH_LONG).show(); + } } @Override public void onFailure(@NonNull Call call, @NonNull Throwable t) { Log.wtf("err", t.fillInStackTrace()); + Toast.makeText(context, context.getString(R.string.authentication_login_failed), Toast.LENGTH_LONG).show(); + } }); } - - } - diff --git a/app/src/main/res/anim/slide_in_bottom.xml b/app/src/main/res/anim/slide_in_bottom.xml new file mode 100644 index 0000000..da3edb3 --- /dev/null +++ b/app/src/main/res/anim/slide_in_bottom.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_bottom.xml b/app/src/main/res/anim/slide_out_bottom.xml new file mode 100644 index 0000000..737b8cf --- /dev/null +++ b/app/src/main/res/anim/slide_out_bottom.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_baseline_account_circle_24.xml b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml new file mode 100644 index 0000000..89199eb --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_add_24.xml b/app/src/main/res/drawable/ic_baseline_add_24.xml new file mode 100644 index 0000000..eb23254 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_add_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_close_24.xml b/app/src/main/res/drawable/ic_baseline_close_24.xml new file mode 100644 index 0000000..16d6d37 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_close_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_help_24.xml b/app/src/main/res/drawable/ic_baseline_help_24.xml new file mode 100644 index 0000000..c0c9268 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_help_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_person_pin_24.xml b/app/src/main/res/drawable/ic_baseline_person_pin_24.xml new file mode 100644 index 0000000..fd6018c --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_person_pin_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_settings_24.xml b/app/src/main/res/drawable/ic_baseline_settings_24.xml new file mode 100644 index 0000000..41a82ed --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_settings_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_video_library_24.xml b/app/src/main/res/drawable/ic_baseline_video_library_24.xml new file mode 100644 index 0000000..2259eaf --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_video_library_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml deleted file mode 100644 index 781f51b..0000000 --- a/app/src/main/res/layout/activity_login.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -