1
0
mirror of https://framagit.org/tom79/fedilab-tube synced 2025-06-05 21:09:11 +02:00

168 Commits
1.5.2 ... 1.9.0

Author SHA1 Message Date
6ae42ffefe Allow to change thumbnail for Playlists 2020-11-28 17:56:16 +01:00
3a8c82ce63 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!52
2020-11-28 16:48:55 +01:00
04c2b277ce New Crowdin updates 2020-11-28 16:48:55 +01:00
962462ff84 Fix some bugs 2020-11-28 16:41:21 +01:00
964b0f2690 Fix some bugs when playing 2020-11-28 14:54:47 +01:00
4b25b61680 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!51
2020-11-28 10:40:17 +01:00
61c3735e57 New Crowdin updates 2020-11-28 10:40:16 +01:00
b0e29c0ba4 Some fixes 2020-11-28 10:33:13 +01:00
e7f55aace9 Fix issue #117 2020-11-28 10:26:20 +01:00
2955206b07 Some improvements with nsfw dialog 2020-11-28 09:32:31 +01:00
b59d97279d Fix issue #115 - Filter with remote accounts does not work 2020-11-28 09:20:44 +01:00
7d9e299940 Update release notes 2020-11-27 19:00:57 +01:00
e15252a0f8 Some fixes 2020-11-27 18:56:37 +01:00
e0907f1dc8 Swipe to change timelines 2020-11-27 18:36:31 +01:00
1107391c43 Fix a crash 2020-11-27 15:00:25 +01:00
2500035c33 Fix issue #58 - Remove more option menu for other channels 2020-11-27 14:29:29 +01:00
24ad4dbc0f Fix issue #58 - Allow to search channels 2020-11-27 14:06:42 +01:00
550394a5e4 Merge branch 'improve_comments' into develop
# Conflicts:
#	app/src/main/java/app/fedilab/fedilabtube/drawer/CommentListAdapter.java
2020-11-27 11:39:07 +01:00
720c13fa2d add decoration 2020-11-27 11:38:36 +01:00
a02b8b79c1 some tests 2020-11-26 14:16:44 +01:00
c2f99e130d clean adapter for comment 2020-11-25 15:11:13 +01:00
250aa03e9a some tries 2020-11-25 15:08:38 +01:00
dd7d253a1b Fix orientation issues 2020-11-25 11:26:14 +01:00
f2b46fffe0 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!50
2020-11-25 09:34:44 +01:00
60630cc4ea New Crowdin updates 2020-11-25 09:34:44 +01:00
85164c18e9 Fix issue #99 2020-11-25 09:31:39 +01:00
3634e5e232 Some fixes 2020-11-24 17:32:18 +01:00
f7d44cb547 Some fixes 2020-11-24 13:50:06 +01:00
85b89507db Fix issue #113 2020-11-23 18:37:26 +01:00
7415b752cc Release 1.8.0 2020-11-22 17:03:18 +01:00
0a52060223 Merge remote-tracking branch 'origin/develop' into develop 2020-11-22 16:46:11 +01:00
1024b1e6f9 color fixes + update lib 2020-11-22 16:46:05 +01:00
23fc061711 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!49
2020-11-22 16:44:56 +01:00
bfa3ede06b New Crowdin updates 2020-11-22 16:44:55 +01:00
c7f6cdc8c6 Fix indentation 2020-11-22 11:15:49 +01:00
58f280d347 Fix issue #106 2020-11-22 11:15:31 +01:00
0715824ae1 Fix issue #108 2020-11-22 11:04:46 +01:00
5540c8cacc Fix issue #109 2020-11-22 10:59:30 +01:00
14efbdd08f Some fixes 2020-11-21 18:54:54 +01:00
7ceb04d548 Fix remote videos not playing 2020-11-21 18:51:30 +01:00
e9608f63db Prepare release 1.8.0 2020-11-21 17:26:28 +01:00
64e1c7ca81 Update release notes 2020-11-21 17:24:28 +01:00
7823b30900 Merge remote-tracking branch 'origin/develop' into develop 2020-11-21 17:17:42 +01:00
1e45e4454c Change profile picture for channels 2020-11-21 17:17:34 +01:00
1dd3a193c5 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!48
2020-11-21 14:17:16 +01:00
30416837a9 New Crowdin updates 2020-11-21 14:17:16 +01:00
363132d331 Fix 2020-11-21 11:06:26 +01:00
ebc0d744ed Fix 2020-11-21 09:59:33 +01:00
d685031ee8 Fix upload 2020-11-21 09:37:18 +01:00
3ea012f62e Change lib 2020-11-20 18:48:29 +01:00
9a06f5660b Some fixes 2020-11-20 15:03:06 +01:00
dff76aada1 Some fixes 2020-11-20 08:58:28 +01:00
50a9f8a1b0 Some improvements 2020-11-19 18:08:28 +01:00
8ff3b81112 Some fixes 2020-11-19 12:00:39 +01:00
38f73a5d60 Some fixes 2020-11-18 19:15:19 +01:00
15f6835a0c Some fixes 2020-11-18 19:04:54 +01:00
84e3264726 Some fixes 2020-11-18 18:15:45 +01:00
dbd068d95f Some fixes 2020-11-18 17:24:18 +01:00
acba219e44 Fix issue #85 2020-11-18 15:44:47 +01:00
c8e7c23855 Fix issue #89 2020-11-18 15:07:22 +01:00
f0ff8a6feb Some fixes with video menu 2020-11-18 10:09:29 +01:00
91a1380fef Fix issue #91 2020-11-18 10:00:25 +01:00
3351ef7d91 Fix issue #76 2020-11-17 18:49:43 +01:00
564cda58a5 Merge remote-tracking branch 'origin/develop' into develop 2020-11-17 18:31:17 +01:00
3233fe673d Some fixes 2020-11-17 18:30:56 +01:00
8cc8b284ce Some fixes 2020-11-17 18:10:45 +01:00
3ecdedc17c Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!47
2020-11-17 17:55:52 +01:00
8f361c605a New Crowdin updates 2020-11-17 17:55:51 +01:00
9d599e8b57 some improvements 2020-11-17 17:47:10 +01:00
9c676d8002 some improvements 2020-11-16 18:54:59 +01:00
8c95554d8e Fix issue #70 2020-11-15 18:09:14 +01:00
3ed5248c2a Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!46
2020-11-15 11:49:35 +01:00
32990932ad New Crowdin updates 2020-11-15 11:49:34 +01:00
6d0a47903c Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!45
2020-11-15 11:40:01 +01:00
05eaa196b4 Prepare release 1.7.0 2020-11-15 11:34:18 +01:00
2cd076bfb8 Comment issue #46 - Allow to delete history 2020-11-15 11:27:38 +01:00
02cd267cae Fix issue #68 - Videos in unlisted playlists cannot be displayed 2020-11-15 09:54:55 +01:00
21394cb585 New translations strings.xml (Polish) 2020-11-15 03:16:43 +01:00
73cd48b94a Release 1.7.0 2020-11-14 19:13:59 +01:00
ea2cf58e5f Merge remote-tracking branch 'origin/develop' into develop 2020-11-14 17:52:32 +01:00
2f3e29b037 Improve comments 2020-11-14 17:52:17 +01:00
33d597c2c0 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!44
2020-11-14 17:49:49 +01:00
66afb3f4ee New Crowdin updates 2020-11-14 17:49:48 +01:00
dad94d753d Remove lib 2020-11-14 17:19:37 +01:00
1727bebf58 update release notes 2020-11-14 15:26:36 +01:00
37576c69ce fixes 2020-11-14 15:22:48 +01:00
b8f83a7227 Merge branch 'bug_fixes_1-6-0' into develop
# Conflicts:
#	app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
2020-11-14 15:21:58 +01:00
3a14abaf2e fixes 2020-11-14 15:18:16 +01:00
0e03a55aef Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!43
2020-11-14 15:10:47 +01:00
931fb30330 New Crowdin updates 2020-11-14 15:10:47 +01:00
b893dc9c4f Merge remote-tracking branch 'origin/develop' into develop 2020-11-14 15:10:27 +01:00
f6ddd99449 Last fixes 2020-11-14 15:09:52 +01:00
ddcbbfe670 Last fixes 2020-11-14 15:05:44 +01:00
0f7438fa54 Some fixes 2020-11-14 12:19:37 +01:00
fbbab1db68 Some fixes 2020-11-14 09:50:48 +01:00
15725dceb0 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!42
2020-11-13 18:46:58 +01:00
1bcbcec8b8 New Crowdin updates 2020-11-13 18:46:57 +01:00
c3e475be6f Allow to export/import 2020-11-13 18:45:55 +01:00
150a81adc6 Some fixes 2020-11-12 17:08:43 +01:00
a984607ee8 Update release notes 2020-11-11 18:28:50 +01:00
2bf929986e Change button 2020-11-11 15:47:42 +01:00
860edec2e6 Follow remote accounts 2020-11-11 15:36:15 +01:00
90cfcbb7ae Fix issue #67 - Reaching profile edition from the account activity 2020-11-11 11:36:01 +01:00
c63048730f Fix issue #62 - Errors with pull to refresh 2020-11-11 11:13:29 +01:00
55bbafdbb5 Fix issue #63 - Reach owner from channels 2020-11-11 10:42:40 +01:00
0923a07e42 Fix issue #59 - Follow button from sepia search 2020-11-11 10:37:49 +01:00
431c21e066 Last fixes 2020-11-11 10:34:28 +01:00
17c84f6c37 Switch from accounts 2020-11-10 18:44:48 +01:00
58f10d9372 Add the logic 2020-11-09 18:48:10 +01:00
dfdda7627f Release 1.6.0 2020-11-08 17:48:13 +01:00
1711826c43 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!41
2020-11-08 17:42:24 +01:00
4627de23b4 New Crowdin updates 2020-11-08 17:42:24 +01:00
023ab2d4b2 Release 1.6.0 2020-11-08 17:42:01 +01:00
2a375318ea fix issue link 2020-11-08 16:50:20 +01:00
fee593d059 Fix issue #44 - Sync NSFW + add them in settings to apply them. 2020-11-08 16:45:38 +01:00
fe3546e282 Fix issue #57 - Allow to share channel and account links 2020-11-08 10:43:27 +01:00
b61b6868a6 Fix issue #55 - Honor downloads disabled 2020-11-08 10:27:40 +01:00
2f8ecd1f3e Prepare release 2020-11-07 17:23:53 +01:00
8a9ead3f0d Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!40
2020-11-07 15:55:16 +01:00
43e2762d4d New Crowdin updates 2020-11-07 15:55:16 +01:00
8ab237a957 Fix issue #47 - Seek to last known position 2020-11-07 15:51:38 +01:00
ffa5d0883a Update release notes 2020-11-07 10:42:19 +01:00
14f0a47f52 Fix issue #40 - Allow search to resolve peertube links 2020-11-07 10:38:30 +01:00
4c1e466866 Fix issue #42 - Allow to display channels from playing video activity 2020-11-07 10:24:56 +01:00
24c6f79b51 small fix 2020-11-07 10:17:45 +01:00
8c958a2563 Fix issue #31 - Show more content when available (with a toggle button) 2020-11-07 10:09:58 +01:00
02cc00780d Merge remote-tracking branch 'origin/develop' into develop 2020-11-07 09:43:14 +01:00
d13cce3997 Fix issue #39 - Allow to display videos in smaller lists 2020-11-07 09:42:56 +01:00
985835429b Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!39
2020-11-06 19:10:28 +01:00
00751cedab New Crowdin updates 2020-11-06 19:10:28 +01:00
c4e85a7161 Some improvements 2020-11-06 19:09:37 +01:00
253b61fb11 Fix issue #29 - Accept URL for instances 2020-11-06 18:52:29 +01:00
54ffbe2e15 Fix issue #30 2020-11-06 18:40:55 +01:00
86d9ba930c Useless translations 2020-11-06 18:22:56 +01:00
fb96efc8cf Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!38
2020-11-06 18:01:22 +01:00
aaac1652e9 New Crowdin updates 2020-11-06 18:01:21 +01:00
c8fc98ee71 Add torrent 2020-11-06 17:32:12 +01:00
4457259dfd Update README.md 2020-11-05 18:03:21 +01:00
6dbb11f6e9 Fix notification settings 2020-11-05 17:56:26 +01:00
08a4b4b49a Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!37
2020-11-05 17:53:29 +01:00
4afd2ca341 New Crowdin updates 2020-11-05 17:53:29 +01:00
0c048877e0 Some new features 2020-11-05 17:38:57 +01:00
825a74de4a Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!36
2020-11-04 18:55:41 +01:00
79ca0ceb88 New Crowdin updates 2020-11-04 18:55:41 +01:00
a5ccc9bf6f Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!35
2020-11-04 18:40:32 +01:00
685467266a New Crowdin updates 2020-11-04 18:40:31 +01:00
599e53b10c Merge remote-tracking branch 'origin/develop' into develop 2020-11-04 18:40:21 +01:00
029b8b57ae push notifications 2020-11-04 18:39:45 +01:00
631264eb57 push notifications 2020-11-04 17:43:38 +01:00
e7eef5b760 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!34
2020-11-03 07:32:14 +01:00
59741e5979 New Crowdin updates 2020-11-03 07:32:14 +01:00
0f38ad180a Allow to edit profile + profile picture 2020-11-01 18:34:53 +01:00
fdc6e6e325 Allow to edit profile 2020-10-31 18:24:52 +01:00
ed9e79496a Auto play video when ended 2020-10-31 10:37:17 +01:00
4f909417f1 Fix issue #14 2020-10-30 16:21:56 +01:00
aecb4034ad Fix issue #20 2020-10-30 14:45:37 +01:00
f0335d96d2 Fix issue #18 2020-10-29 18:56:57 +01:00
65f3886355 upgrade lib 2020-10-29 10:05:40 +01:00
8e2f1fb8fe Merge remote-tracking branch 'origin/develop' into develop 2020-10-28 15:03:15 +01:00
852cfee310 Fix double click for pausing and exit fullscreen 2020-10-28 15:03:07 +01:00
6620a12957 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!33
2020-10-28 08:25:38 +01:00
11e8135cbd New translations strings.xml (German) 2020-10-27 11:45:01 +01:00
824c4e0cbb Comment #16 - Redirect to another app if the URL can't be open with TubeLab 2020-10-26 19:02:55 +01:00
9af7934448 Fix issue #16 2020-10-26 14:38:51 +01:00
4ffa027e8d Merge remote-tracking branch 'origin/develop' into develop 2020-10-25 17:40:27 +01:00
7e8ab3359a Add CHANGELOG + CONTRIBUTING.md + issue_template.md + FUNDING.yml 2020-10-25 17:40:09 +01:00
8e72655731 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!32
2020-10-25 09:40:17 +01:00
5c098857bd New Crowdin updates 2020-10-25 09:40:17 +01:00
180 changed files with 11380 additions and 5318 deletions

10
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,10 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: tom79
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: tom79
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

28
CHANGELOG Normal file
View File

@ -0,0 +1,28 @@
# 1.5.2
### Added:
- Enable/disable auto playback
- Enter in full-screen automatically (default disabled)
- Back press pauses the video in full-screen
### Fixed:
- Public timelines don't honor muted accounts
- Comments are not removed when switching to a video without comments
- Some other fixes
--------
# 1.5.1
- Fix some issues
- New translations
--------
# 1.5.0
- Custom default instance depending of the country
- Full managements of comments and their replies (read/post/delete)
- Profile for accounts (displays their channels & videos)
- Fix some issues when posting a comment
- Fix videos not paused after screen lock

17
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,17 @@
CONTRIBUTING
============
### Localizations:
TubeLab works only with [Crowdin](https://crowdin.com/project/tubelab), which offers nice tools for helping in translations.
New translations will be automatically merged in a branch.
If your language is not listed, please ask me to add it. If you prefer to work on an XML file, you should be able [to upload it with Crowdin](https://support.crowdin.com/xml-configuration/).
Crowdin will not pick up changes in develop branch, that's why all translations should be done with this tool.
### Issues:
Issues are handled on Github at: https://github.com/stom79/TubeLab/issues, before opening an issue, please check it has not yet been submitted by someone else
### Contribution to code:
Your contributions are welcomed, but please, use this repo https://framagit.org/tom79/fedilab-tube. You can create PR to the dev branch.

View File

@ -6,7 +6,10 @@ The other app is **[TubeLab](#TubeLab)** a Peertube Android app working for all
## <a name="TubeLab">TubeLab</a> ## <a name="TubeLab">TubeLab</a>
Tubelab is an Android app for Peertube (GNU GPLv3). Tubelab is an Android app for Peertube (GNU GPLv3). <img src='https://img.shields.io/f-droid/v/app.fedilab.tubelab?include_prereleases' />
[<img alt='Get it on Google Play' src='./images/get-it-on-play.png' height="80"/>](https://play.google.com/store/apps/details?id=app.fedilab.tubelab)
&nbsp;&nbsp;[<img alt='Get it on F-Droid' src='./images/get-it-on-fdroid.png' height="80"/>](https://f-droid.org/packages/app.fedilab.tubelab/)
### Not authenticated mode ### Not authenticated mode
@ -34,6 +37,11 @@ Many features are available with this mode:
TubeAcad est une application Android open source (GNU GPLv3) pour les instances Peertube académiques. Lauthentification se fait par adresse mail, linstance est automatiquement détectée. Il est également possible sur certaines instances de créer son compte depuis lapplication. TubeAcad est une application Android open source (GNU GPLv3) pour les instances Peertube académiques. Lauthentification se fait par adresse mail, linstance est automatiquement détectée. Il est également possible sur certaines instances de créer son compte depuis lapplication.
[<img alt='Get it on Google Play' src='./images/get-it-on-play.png' height="80"/>](https://play.google.com/store/apps/details?id=app.fedilab.fedilabtube)
&nbsp;&nbsp;[<img alt='Get it on F-Droid' src='./images/get-it-on-fdroid.png' height="80"/>](https://f-droid.org/packages/app.fedilab.fedilabtube/)
### Mode non authentifié ### Mode non authentifié
Ce mode permet de visionner les vidéos sur différentes instances (en sélectionnant une instance académique). Cependant, vous ne pourrez pas interagir totalement avec les vidéos. Vous pourrez : Ce mode permet de visionner les vidéos sur différentes instances (en sélectionnant une instance académique). Cependant, vous ne pourrez pas interagir totalement avec les vidéos. Vous pourrez :
@ -60,19 +68,3 @@ Si vous connectez votre compte, vous pourrez interagir avec les vidéos :
- Signaler des vidéos ou des comptes - Signaler des vidéos ou des comptes
- Voir l'historique - Voir l'historique
### Downloads
#### TubeAcad
[Fdroid](https://f-droid.org/packages/app.fedilab.fedilabtube/)
[GooglePlay](https://play.google.com/store/apps/details?id=app.fedilab.fedilabtube)
#### TubeLab
[Fdroid](https://f-droid.org/packages/app.fedilab.tubelab/)
[GooglePlay](https://play.google.com/store/apps/details?id=app.fedilab.tubelab)

View File

@ -11,8 +11,8 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion 30
versionCode 21 versionCode 29
versionName "1.5.2" versionName "1.9.0"
multiDexEnabled true multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -97,28 +97,29 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.2.1' implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0' implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.navigation:navigation-fragment:2.3.0' implementation 'androidx.navigation:navigation-fragment:2.3.1'
implementation "androidx.fragment:fragment:1.2.5" implementation "androidx.fragment:fragment:1.2.5"
implementation 'androidx.navigation:navigation-ui:2.3.0' implementation 'androidx.navigation:navigation-ui:2.3.1'
implementation ("androidx.navigation:navigation-dynamic-features-fragment:2.3.0") implementation ("androidx.navigation:navigation-dynamic-features-fragment:2.3.1")
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.browser:browser:1.2.0' implementation 'androidx.browser:browser:1.2.0'
implementation 'androidx.documentfile:documentfile:1.0.1'
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'com.github.GrenderG:Toasty:1.4.2' implementation 'com.github.GrenderG:Toasty:1.4.2'
implementation 'com.google.android.exoplayer:exoplayer:2.10.6' implementation 'com.google.android.exoplayer:exoplayer:2.12.1'
implementation 'com.google.android.exoplayer:extension-mediasession:2.10.6' implementation 'com.google.android.exoplayer:extension-mediasession:2.12.1'
implementation "com.github.mabbas007:TagsEditText:1.0.5" implementation "com.github.mabbas007:TagsEditText:1.0.5"
implementation "com.github.bumptech.glide:glide:4.11.0" implementation "com.github.bumptech.glide:glide:4.11.0"
annotationProcessor "com.github.bumptech.glide:compiler:4.11.0" annotationProcessor "com.github.bumptech.glide:compiler:4.11.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "net.gotev:uploadservice:3.5.2" implementation "net.gotev:uploadservice:4.5.1"
implementation "net.gotev:uploadservice-okhttp:3.5.2" implementation "net.gotev:uploadservice-okhttp:4.5.1"
implementation "com.google.code.gson:gson:2.8.6" implementation "com.google.code.gson:gson:2.8.6"
implementation 'androidx.media:media:1.2.0' implementation 'androidx.media:media:1.2.0'
implementation 'com.github.ybq:Android-SpinKit:1.4.0' implementation 'com.github.ybq:Android-SpinKit:1.4.0'
@ -126,7 +127,13 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.github.mancj:MaterialSearchBar:0.8.5' implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
implementation "com.github.TorrentStream:TorrentStream-Android:2.7.0"
implementation "io.github.kobakei:ratethisapp:1.2.0" implementation "io.github.kobakei:ratethisapp:1.2.0"
implementation 'com.github.HITGIF:TextFieldBoxes:1.4.5' implementation 'com.github.vkay94:DoubleTapPlayerView:1.0.0'
implementation "androidx.work:work-runtime:2.4.0"
implementation "androidx.work:work-runtime-ktx:2.4.0"
implementation 'jp.wasabeef:glide-transformations:4.0.0'
} }

View File

@ -8,6 +8,7 @@
<color name="tag_color_text">#FAFAFA</color> <color name="tag_color_text">#FAFAFA</color>
<color name="positive_thumbs">#2b90d9</color> <color name="positive_thumbs">#2b90d9</color>
<color name="negative_thumbs">#F44336</color> <color name="negative_thumbs">#F44336</color>
<color name="backgroundDark">#DD000000</color>
<color name="red_1">#F44336</color> <color name="red_1">#F44336</color>
<color name="gray_light">#80808080</color>
</resources> </resources>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" translatable="false">TubeAcad</string> <string name="app_name" translatable="false">TubeAcad</string>
<string name="app_id" translatable="false">app.fedilab.fedilabtube</string>
<string name="set_video_mode_choice" translatable="false">set_video_mode_choice</string> <string name="set_video_mode_choice" translatable="false">set_video_mode_choice</string>
<string name="set_video_minimize_choice" translatable="false">set_video_minimize_choice</string> <string name="set_video_minimize_choice" translatable="false">set_video_minimize_choice</string>
<string name="set_video_language_choice" translatable="false">set_video_language_choice</string> <string name="set_video_language_choice" translatable="false">set_video_language_choice</string>
@ -9,8 +10,61 @@
<string name="set_autoplay_choice" translatable="false">set_autoplay_choice</string> <string name="set_autoplay_choice" translatable="false">set_autoplay_choice</string>
<string name="set_theme_choice" translatable="false">set_theme_choice</string> <string name="set_theme_choice" translatable="false">set_theme_choice</string>
<string name="set_fullscreen_choice" translatable="false">set_fullscreen_choice</string> <string name="set_fullscreen_choice" translatable="false">set_fullscreen_choice</string>
<string name="set_autoplay_next_video_choice" translatable="false">set_autoplay_next_video_choice</string>
<string name="set_store_in_history" translatable="false">set_store_in_history</string>
<string name="set_play_screen_lock_choice" translatable="false">set_play_screen_lock_choice</string>
<string name="set_video_in_list_choice" translatable="false">set_video_in_list_choice</string>
<string name="set_video_sensitive_choice" translatable="false">set_video_sensitive_choice</string>
<string name="set_video_in_list">Vidéos dans une liste</string>
<string name="set_video_in_list_description">Change la mise en page pour afficher les vidéos dans une liste</string>
<string name="_retry">Réessayer</string>
<string name="refresh_token_failed">Échec de rafraîchissement du jeton d\'accès</string>
<string name="refresh_token_failed_message">Vous pouvez réessayer de le rafraîchir ou simplement déconnecter le compte</string>
<string name="export_list">Exporter</string>
<string name="import_list">Importer</string>
<string name="originally_published">Date de publication</string>
<string name="delete_history">Supprimer l\'historique de vidéos</string>
<string name="delete_history_confirm">Êtes vous sur de vouloir supprimer toutes les vidéos de votre historique ?</string>
<string name="export_notification_title">Exportation réussie !</string>
<string name="export_notification_content">Cliquer ici pour envoyer l\'exportation par mèl.</string>
<string name="export_notification_subjet">Nouvelle liste de lecture</string>
<string name="export_notification_body">Ouvrez la pièce jointe avec l\'application TubeAcad</string>
<string name="show_more">Montrer plus</string>
<string name="show_less">Montrer moins</string>
<string name="no_instances">Aucune instance !</string>
<string name="set_play_screen_lock">Verrouillage d\'écran</string>
<string name="set_play_screen_lock_description">Continuer à lire des vidéos lorsque l\'écran est verrouillé</string>
<string name="change_profile_picture">Modifier la photo de profil</string>
<string name="account_updated">Le compte a été mis à jour !</string>
<string name="new_video">Nouvelle vidéo</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="notif_new_video">Nouvelle vidéo depuis vos souscriptions</string>
<string name="notif_new_comment">Nouveau commentaire sur votre vidéo</string>
<string name="notif_blocked">Une de vos vidéos est bloquée/débloquée</string>
<string name="notif_video_published">Vidéo publiée (après transcodage / mise à jour programmée)</string>
<string name="notif_video_imported">Import de vidéo terminé</string>
<string name="notif_new_followers">Vous ou votre chaîne avez/a un·e nouvel·le abonné·e</string>
<string name="notif_video_mention">Quelqu\'un vous a mentionné dans les commentaires d\'une vidéo</string>
<string name="notif_abuse_received">Un signalement d\'abus a reçu un nouveau message</string>
<string name="notif_abuse_accepted">Un de vos rapports d\'abus a été accepté ou rejeté par les modérateurs</string>
<string name="save">Enregistrer</string>
<string name="set_autoplay_next_video">Lire automatiquement la vidéo suivante</string>
<string name="set_autoplay_next_video_description">Quand une vidéo est terminée, lire la prochaine vidéo suggérée.</string>
<string name="enable_history">Activer l\'historique</string>
<string name="set_autoplay">Lecture automatique</string> <string name="set_autoplay">Lecture automatique</string>
<string name="set_autoplay_description">Si activé, les vidéos seront lues automatiquement</string> <string name="set_autoplay_description">Si activé, les vidéos seront lues automatiquement</string>
@ -25,6 +79,16 @@
<item>Automatique</item> <item>Automatique</item>
</string-array> </string-array>
<string name="refresh_every">Mettre à jour toutes les :</string>
<string-array name="refresh_time">
<item>Jamais</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 heure</item>
<item>2 heures</item>
<item>6 heures</item>
<item>12 heures</item>
</string-array>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="zero">%d réponse</item> <item quantity="zero">%d réponse</item>
@ -115,8 +179,12 @@
<string name="app_logo">Logo de lapplication</string> <string name="app_logo">Logo de lapplication</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Abonnements</string> <string name="subscriptions">Abonnements</string>
<string name="delete_instance">Supprimer l\'instance</string>
<string name="delete_instance_confirm">Etes-vous sûr de vouloir supprimer cette instance ?</string>
<string name="delete_comment">Supprimer le commentaire</string> <string name="delete_comment">Supprimer le commentaire</string>
<string name="delete_comment_confirm">Etes-vous sûr de vouloir supprimer ce commentaire ?</string> <string name="delete_comment_confirm">Etes-vous sûr de vouloir supprimer ce commentaire ?</string>
<string name="set_video_mode">Mode pour les vidéos</string> <string name="set_video_mode">Mode pour les vidéos</string>
<string name="filter">Filtrer</string> <string name="filter">Filtrer</string>
<string name="sepia_search">Recherche sépia</string> <string name="sepia_search">Recherche sépia</string>
@ -137,6 +205,9 @@
<string name="all_of_these_tags">Tous ces labels</string> <string name="all_of_these_tags">Tous ces labels</string>
<string name="one_of_these_tags">Un de ces labels</string> <string name="one_of_these_tags">Un de ces labels</string>
<string name="apply_filter">Appliquer le filtre</string> <string name="apply_filter">Appliquer le filtre</string>
<string name="playback_speed">Vitesse du lecteur</string>
<string name="normal">Normal</string>
<string-array name="sort_by_array"> <string-array name="sort_by_array">
<item>Meilleurs résultats</item> <item>Meilleurs résultats</item>
<item>Les plus récentes</item> <item>Les plus récentes</item>
@ -196,7 +267,9 @@
<string name="add_public_reply">Répondre publiquement</string> <string name="add_public_reply">Répondre publiquement</string>
<string name="send_comment">Envoyer un commentaire</string> <string name="send_comment">Envoyer un commentaire</string>
<string name="all">Tout</string> <string name="all">Tout</string>
<string name="activity">Activité</string>
<string name="app">App</string>
<string name="fetch_notification_channel_name">Mise à jour des notifications</string>
<string name="peertube_video_report_success"><![CDATA[ Votre signalement <b>%1$s</b> a été accepté]]></string> <string name="peertube_video_report_success"><![CDATA[ Votre signalement <b>%1$s</b> a été accepté]]></string>
<string name="reply">Répondre</string> <string name="reply">Répondre</string>
<!-- end languages --> <!-- end languages -->
@ -225,15 +298,26 @@
<string name="report_account">Signaler le compte</string> <string name="report_account">Signaler le compte</string>
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normal</item> <item>Normal</item>
<item>Streaming</item> <item>Navigateur</item>
<item>Flux direct</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_video_quality"> <string-array name="settings_video_quality">
<item>Élevée</item> <item>Élevée</item>
<item>Moyenne</item> <item>Moyenne</item>
<item>Faible</item> <item>Faible</item>
</string-array> </string-array>
<string name="unlimited">Illimité</string>
<string name="mb">Mo</string>
<string name="gb">Go</string>
<string name="total_video_quota">Total du quota vidéo</string>
<string name="daily_video_quota">Quota vidéo journalier</string>
<string name="nsfw_title_warning">Contenu explicite ou sensible</string>
<string name="nsfw_message_warning">Cette vidéo contient du contenu sensible. Êtes-vous sûr·e de vouloir la regarder ?</string>
<string name="set_autoplay_next_video_settings">Lecture automatique</string>
<string name="unfollow_confirm">Voulez-vous vous désabonner de ce compte ?</string> <string name="unfollow_confirm">Voulez-vous vous désabonner de ce compte ?</string>
<string name="no_playlist">Aucune liste de lecture !</string>
<string name="title_video_peertube">Titre de la vidéo</string> <string name="title_video_peertube">Titre de la vidéo</string>
<string name="join_peertube">Rejoignez Peertube</string> <string name="join_peertube">Rejoignez Peertube</string>
<string name="agreement_check_peertube">J\'ai au moins 16 ans et je suis d\'accord avec les %1$s de cette instance</string> <string name="agreement_check_peertube">J\'ai au moins 16 ans et je suis d\'accord avec les %1$s de cette instance</string>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="/TubeAcad/" />
</paths>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.fedilab.fedilabtube">
<application
android:name=".FedilabTube"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name=".MainActivity"
tools:node="merge">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.tubelab" />
<data android:pathPattern=".*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.tubelab" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.fedilab.fedilabtube">
<application
android:name=".FedilabTube"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name=".PeertubeActivity"
tools:node="mergeOnlyAttributes">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- The app is a good candidate for URL in https://domain.name/videos/watch/xxxxx-->
<data
android:host="*"
android:pathPrefix="/videos/watch/"
android:scheme="https" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -12,7 +12,7 @@ C'est un mode limité où vous pouvez faire certaines actions:
De nombreuses fonctionnalités sont disponibles avec ce mode: De nombreuses fonctionnalités sont disponibles avec ce mode:
- Rédiger/supprimer des commentaires - Rédiger/supprimer des commentaires
- Télécharger/supprimer/modifier des vidéos - Téléverser/supprimer/modifier des vidéos
- Gérer (créer/modifier/supprimer) les chaînes et les listes de lecture - Gérer (créer/modifier/supprimer) les chaînes et les listes de lecture
- Suivre/ne pas suivre les canaux - Suivre/ne pas suivre les canaux
- Pouces vers le haut/vers le bas - Pouces vers le haut/vers le bas

View File

@ -1,8 +1,15 @@
Added: Added:
- Enable/disable auto playback - Allow to search channels
- Enter in fullscreen automatically (default disabled) - Show storage quota
- Back press pauses the video in fullscreen - Warning on Playing NSFW videos
- Swipe to change timelines
Fixes: Changed:
- Public timelines don't honor muted accounts - Improve comment threads
- Comments are not removed when switching to a video without comments - Comment composer in full-screen
- Swipe to change timeline
Fixed:
- Status bar for fullscreen not removed
- Filter for subscriptions not working with remote accounts
- Some crashes

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="zero">%d ردود</item> <item quantity="zero">%d ردود</item>
<item quantity="one">ردّ واحد %d</item> <item quantity="one">ردّ واحد %d</item>
@ -42,9 +67,28 @@
<string name="upload_video">إرسال</string> <string name="upload_video">إرسال</string>
<string name="image_preview">معاينة الصورة</string> <string name="image_preview">معاينة الصورة</string>
<string name="file_to_upload">اختر الملف المراد ارساله</string> <string name="file_to_upload">اختر الملف المراد ارساله</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">قناة</string> <string name="channel">قناة</string>
<string name="videos">الفيديوهات</string> <string name="videos">الفيديوهات</string>
<string name="channels">القنوات</string> <string name="channels">القنوات</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">موافق</string> <string name="yes">موافق</string>
<string name="no">لا</string> <string name="no">لا</string>
<string name="cancel">إلغاء</string> <string name="cancel">إلغاء</string>
@ -64,6 +108,7 @@
<string name="video_uploaded_action">Tap here to edit the video data.</string> <string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">طرأ هناك خطأ أثناء اختيار الوسائط!</string> <string name="toot_select_image_error">طرأ هناك خطأ أثناء اختيار الوسائط!</string>
<string name="download_file">تنزيل %1$s</string> <string name="download_file">تنزيل %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">الخصوصية</string> <string name="action_privacy">الخصوصية</string>
<string name="action_logout">تسجيل الخروج</string> <string name="action_logout">تسجيل الخروج</string>
<string name="login">تسجيل الدخول</string> <string name="login">تسجيل الدخول</string>
@ -82,8 +127,15 @@
<string name="toast_error_loading_account">طرأ هناك خطأ أثناء التحوّل مِن حساب إلى آخر!</string> <string name="toast_error_loading_account">طرأ هناك خطأ أثناء التحوّل مِن حساب إلى آخر!</string>
<string name="toast_error_search">وقع خطأ أثناء عملية البحث!</string> <string name="toast_error_search">وقع خطأ أثناء عملية البحث!</string>
<string name="nothing_to_do">لا يمكن اتخاذ أي إجراء</string> <string name="nothing_to_do">لا يمكن اتخاذ أي إجراء</string>
<string name="action_follow">اتبع</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">كتم</string> <string name="action_mute">كتم</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">البحث</string> <string name="search">البحث</string>
<string name="delete">حذف</string> <string name="delete">حذف</string>
<string name="action_lists_confirm_delete">هل تود فعلا حذف هذه القائمة ؟</string> <string name="action_lists_confirm_delete">هل تود فعلا حذف هذه القائمة ؟</string>
@ -97,6 +149,8 @@
<string name="app_logo">شعار التطبيق</string> <string name="app_logo">شعار التطبيق</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">الاشتراكات</string> <string name="subscriptions">الاشتراكات</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">حذف التعليق</string> <string name="delete_comment">حذف التعليق</string>
<string name="delete_comment_confirm">هل أنت متأكد من أنك تود حذف هذا التعليق؟</string> <string name="delete_comment_confirm">هل أنت متأكد من أنك تود حذف هذا التعليق؟</string>
<string name="set_video_mode">أسلوب عرض الفيديوهات</string> <string name="set_video_mode">أسلوب عرض الفيديوهات</string>
@ -181,7 +235,18 @@
<string name="send_comment">ارسل تعليق</string> <string name="send_comment">ارسل تعليق</string>
<string name="all">الكل</string> <string name="all">الكل</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">قوائم التشغيل</string> <string name="playlists">قوائم التشغيل</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">الاسم العلني</string> <string name="display_name">الاسم العلني</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">يجب عليك إدخال اسم علني!</string> <string name="error_display_name">يجب عليك إدخال اسم علني!</string>
@ -211,7 +276,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>عادي</item> <item>عادي</item>
<item>Webview</item> <item>Webview</item>
<item>تدفق مباشر</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>فاتحة</item> <item>فاتحة</item>
@ -229,7 +295,7 @@
<string name="agreement_check_peertube">أبلُغ مِن العُمر 16 سنة على الأقل وأوافق على %1$s هذا الخادم</string> <string name="agreement_check_peertube">أبلُغ مِن العُمر 16 سنة على الأقل وأوافق على %1$s هذا الخادم</string>
<string name="edit_profile">عدّل الصفحة التعريفية</string> <string name="edit_profile">عدّل الصفحة التعريفية</string>
<string name="make_an_action">القيام بإجراء</string> <string name="make_an_action">القيام بإجراء</string>
<string name="action_unfollow">إلغاء المتابعة</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -267,6 +333,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">إضافة حساب</string> <string name="add_account">إضافة حساب</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,24 +1,49 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_autoplay">Automatic playback</string> <string name="set_video_in_list">Listenmodus</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_video_in_list_description">Video-Übersicht als Liste anzeigen</string>
<string name="set_fullscreen">Fullscreen</string> <string name="no_instances">Keine Instanzen !</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="show_more">Mehr anzeigen</string>
<string name="show_less">Weniger anzeigen</string>
<string name="set_play_screen_lock">Bildschirmsperre</string>
<string name="set_play_screen_lock_description">Videos weiterhin abspielen, wenn der Bildschirm gesperrt ist</string>
<string name="save">Speichern</string>
<string name="enable_history">Verlauf aktivieren</string>
<string name="change_profile_picture">Profilbild ändern</string>
<string name="set_autoplay">Automatische Wiedergabe</string>
<string name="set_autoplay_description">Wenn aktiviert, werden Videos automatisch abgespielt</string>
<string name="set_fullscreen">Vollbild</string>
<string name="set_fullscreen_description">Videos automatisch im Vollbildmodus öffnen</string>
<string name="set_autoplay_next_video_settings">Automatische Wiedergabe</string>
<string name="set_autoplay_next_video">Automatisch nächstes Video starten</string>
<string name="set_autoplay_next_video_description">Wenn ein Video endet, nächstes vorgeschlagene starten.</string>
<string name="add_public_reply">Öffentliche Antwort hinzufügen</string> <string name="add_public_reply">Öffentliche Antwort hinzufügen</string>
<string name="originally_published">Ursprünglich veröffentlicht</string>
<string name="activity">Aktivität</string>
<string name="app">Anwendung</string>
<string name="notif_new_video">Neues Video aus deinen Abonnements</string>
<string name="notif_new_comment">Neuer Kommentar zu deinem Video</string>
<string name="notif_blocked">Eines deiner Videos ist blockiert/entsperrt</string>
<string name="notif_video_published">Video veröffentlicht (nach Umkodierung/geplanter Aktualisierung)</string>
<string name="notif_video_imported">Videoimport abgeschlossen</string>
<string name="notif_new_followers">Du oder dein Kanal(e) haben einen neuen Follower</string>
<string name="notif_video_mention">Jemand hat dich in einem Kommentar erwähnt</string>
<string name="notif_abuse_received">Es gibt eine neue Nachricht zu einem Missbrauchsbericht</string>
<string name="notif_abuse_accepted">Ein Missbrauchsbericht wurde von Moderatoren akzeptiert oder abgelehnt</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d Antwort</item> <item quantity="one">%d Antwort</item>
<item quantity="other">%d Antworten</item> <item quantity="other">%d Antworten</item>
</plurals> </plurals>
<string name="reply">Antworten</string> <string name="reply">Antworten</string>
<string name="set_theme">Erscheinungsbild</string> <string name="set_theme">Erscheinungsbild</string>
<string name="set_theme_description">Erlaube Änderungen am Erscheinungsbild</string> <string name="set_theme_description">Erscheinungsbild ändern</string>
<string name="federation_issue">Das Video kann nicht föderiert eingebunden werden!</string> <string name="federation_issue">Das Video kann nicht föderiert eingebunden werden!</string>
<string name="title_home">Startseite</string> <string name="title_home">Startseite</string>
<string name="title_local">Lokal</string> <string name="title_local">Lokal</string>
<string name="title_discover">Mehr erfahren</string> <string name="title_discover">Entdecken</string>
<string name="title_notifications">Benachrichtigungen</string> <string name="title_notifications">Benachrichtigungen</string>
<string name="title_recently_added">Zuletzt hinzugefügt</string> <string name="title_recently_added">Zuletzt hinzugefügt</string>
<string name="title_trending">Beliebt</string> <string name="title_trending">Angesagt</string>
<string name="title_most_liked">Beliebteste</string> <string name="title_most_liked">Beliebteste</string>
<string name="toast_error">Hoppla, es gab einen Fehler!</string> <string name="toast_error">Hoppla, es gab einen Fehler!</string>
<string name="title_muted">Stummgeschaltet</string> <string name="title_muted">Stummgeschaltet</string>
@ -33,21 +58,40 @@
<string name="no_notifications">Keine Benachrichtigungen!</string> <string name="no_notifications">Keine Benachrichtigungen!</string>
<string name="favicon">Favicon</string> <string name="favicon">Favicon</string>
<string name="open_with">Öffnen mit</string> <string name="open_with">Öffnen mit</string>
<string name="action_playlist_edit">Playlist bearbeiten</string> <string name="action_playlist_edit">Wiedergabeliste bearbeiten</string>
<string name="close">Schließen</string> <string name="close">Schließen</string>
<string name="upload_video">Hochladen</string> <string name="upload_video">Hochladen</string>
<string name="image_preview">Bildvorschau</string> <string name="image_preview">Bildvorschau</string>
<string name="file_to_upload">Datei zum Hochladen auswählen</string> <string name="file_to_upload">Datei zum Hochladen auswählen</string>
<string name="new_video">Neues Video</string>
<string name="new_blacklist">Neue Schwarze-Liste-Infos</string>
<string name="new_my_video_published">Dein Video wurde veröffentlicht</string>
<string name="new_my_video_error">Fehler bei Veröffentlichung deines Videos</string>
<string name="new_comment">Neuer Kommentar</string>
<string name="new_follow">Neuer Follower</string>
<string name="channel">Kanal</string> <string name="channel">Kanal</string>
<string name="videos">Videos</string> <string name="videos">Videos</string>
<string name="channels">Kanäle</string> <string name="channels">Kanäle</string>
<string name="refresh_every">Rufe alle ab:</string>
<string-array name="refresh_time">
<item>Nie</item>
<item>15 Minuten</item>
<item>30 Minuten</item>
<item>1 Stunde</item>
<item>2 Stunden</item>
<item>6 Stunden</item>
<item>12 Stunden</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Ja</string> <string name="yes">Ja</string>
<string name="no">Nein</string> <string name="no">Nein</string>
<string name="cancel">Abbrechen</string> <string name="cancel">Abbrechen</string>
<string name="download">Herunterladen</string> <string name="download">Herunterladen</string>
<string name="profile_picture">Profilbild</string> <string name="profile_picture">Profilbild</string>
<string name="update_video">Video aktualisieren</string> <string name="update_video">Video aktualisieren</string>
<string name="remove_from_playlist">Aus Playlist entfernen</string> <string name="remove_from_playlist">Aus Wiedergabeliste entfernen</string>
<string name="date_seconds">%d en</string> <string name="date_seconds">%d en</string>
<string name="date_minutes">%d en</string> <string name="date_minutes">%d en</string>
<string name="date_hours">%d en</string> <string name="date_hours">%d en</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Hier klicken, um die Videodetails zu bearbeiten.</string> <string name="video_uploaded_action">Hier klicken, um die Videodetails zu bearbeiten.</string>
<string name="toot_select_image_error">Fehler beim Wählen des Bildes!</string> <string name="toot_select_image_error">Fehler beim Wählen des Bildes!</string>
<string name="download_file">%1$s heruntergeladen</string> <string name="download_file">%1$s heruntergeladen</string>
<string name="account_updated">Benutzerkonto wurde aktualisiert!</string>
<string name="action_privacy">Datenschutz</string> <string name="action_privacy">Datenschutz</string>
<string name="action_logout">Abmelden</string> <string name="action_logout">Abmelden</string>
<string name="login">Einloggen</string> <string name="login">Einloggen</string>
@ -78,8 +123,15 @@
<string name="toast_error_loading_account">Ein Fehler ist während des Kontowechsels aufgetreten!</string> <string name="toast_error_loading_account">Ein Fehler ist während des Kontowechsels aufgetreten!</string>
<string name="toast_error_search">Ein Fehler ist während der Suche aufgetreten!</string> <string name="toast_error_search">Ein Fehler ist während der Suche aufgetreten!</string>
<string name="nothing_to_do">Keine Aktion möglich</string> <string name="nothing_to_do">Keine Aktion möglich</string>
<string name="action_follow">Folge</string> <string name="action_follow">Abonnieren</string>
<string name="action_mute">Stummschalten</string> <string name="action_mute">Stummschalten</string>
<string name="unlimited">Unbegrenzt</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Suche</string> <string name="search">Suche</string>
<string name="delete">Löschen</string> <string name="delete">Löschen</string>
<string name="action_lists_confirm_delete">Möchtest du diese Liste wirklich dauerhaft löschen?</string> <string name="action_lists_confirm_delete">Möchtest du diese Liste wirklich dauerhaft löschen?</string>
@ -92,7 +144,9 @@
<string name="information" tools:ignore="UnusedResources">Information</string> <string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo der Anwendung</string> <string name="app_logo">Logo der Anwendung</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Abonnements</string> <string name="subscriptions">Abos</string>
<string name="delete_instance">Eine Instanz entfernen</string>
<string name="delete_instance_confirm">Möchtest du diese Instanz wirklich entfernen?</string>
<string name="delete_comment">Kommentar löschen</string> <string name="delete_comment">Kommentar löschen</string>
<string name="delete_comment_confirm">Möchtest du diesen Kommentar wirklich löschen?</string> <string name="delete_comment_confirm">Möchtest du diesen Kommentar wirklich löschen?</string>
<string name="set_video_mode">Videomodus</string> <string name="set_video_mode">Videomodus</string>
@ -132,26 +186,26 @@
<string name="peertube_enable_comments">Videokommentare aktivieren</string> <string name="peertube_enable_comments">Videokommentare aktivieren</string>
<string name="description">Beschreibung</string> <string name="description">Beschreibung</string>
<string name="toast_peertube_video_updated">Das Video wurde aktualisiert!</string> <string name="toast_peertube_video_updated">Das Video wurde aktualisiert!</string>
<string name="register_account">Account erstellen</string> <string name="register_account">Konto erstellen</string>
<string name="email_address">EMailAdresse</string> <string name="email_address">EMailAdresse</string>
<string name="preview">Vorschau</string> <string name="preview">Vorschau</string>
<string name="change_preview">Vorschaubild ändern</string> <string name="change_preview">Vorschaubild ändern</string>
<string name="name">Name</string> <string name="name">Name</string>
<string name="display_more">Mehr anzeigen</string> <string name="display_more">Mehr anzeigen</string>
<string name="no_channels">Keine Kanäle!</string> <string name="no_channels">Keine Kanäle!</string>
<string name="report_helper">Einige Erklärungen zu deinem Bericht</string> <string name="report_helper">Einige Erklärungen zu deiner Meldung</string>
<string name="report_video">Video melden</string> <string name="report_video">Video melden</string>
<string name="report">Bericht</string> <string name="report">Melden</string>
<string name="change_instance">Wähle eine andere Instanz</string> <string name="change_instance">Wähle eine andere Instanz</string>
<string name="my_history">Verlauf</string> <string name="my_history">Verlauf</string>
<string name="edit">Bearbeiten</string> <string name="edit">Bearbeiten</string>
<string name="video_settings">Video-Einstellungen</string> <string name="video_settings">Video-Einstellungen</string>
<string name="app_interface">Benutzeroberfläche</string> <string name="app_interface">Benutzeroberfläche</string>
<string name="set_cache_mode">Zwischenspeicher</string> <string name="set_cache_mode">Zwischenspeicher</string>
<string name="set_video_cache_description">Lege die Größe des Zwischenspeichers für Videos fest (Standard 100Mb)</string> <string name="set_video_cache_description">Lege die Größe des Zwischenspeichers für Videos fest (Standard 100MB)</string>
<string name="set_video_quality_description">Standardqualität für Videos festlegen</string> <string name="set_video_quality_description">Standardqualität für Videos festlegen</string>
<string name="set_quality_mode">Auflösung für Videos</string> <string name="set_quality_mode">Auflösung für Videos</string>
<string name="video_cache_value">Video-Zwischenspeicher: %d Mb</string> <string name="video_cache_value">Video-Zwischenspeicher: %d MB</string>
<string name="captions">Untertitel</string> <string name="captions">Untertitel</string>
<string name="pickup_captions">Untertitel abholen</string> <string name="pickup_captions">Untertitel abholen</string>
<string name="none">Keine</string> <string name="none">Keine</string>
@ -164,22 +218,33 @@
<string name="share">Teilen</string> <string name="share">Teilen</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> hat dein Video <b>%2$s</b> kommentiert]]></string> <string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> hat dein Video <b>%2$s</b> kommentiert]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> folgt deinem Kanal <b>%2$s</b>]]></string> <string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> folgt deinem Kanal <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> folgt deinem Account]]></string> <string name="peertube_follow_account"><![CDATA[<b>%1$s</b> folgt deinem Konto]]></string>
<string name="peertube_video_published"><![CDATA[Dein Video <b>%1$s</b> wurde veröffentlicht]]></string> <string name="peertube_video_published"><![CDATA[Dein Video <b>%1$s</b> wurde veröffentlicht]]></string>
<string name="peertube_video_import_success"><![CDATA[Ihr Video <b>%1$s</b> wurde erfolgreich importiert]]></string> <string name="peertube_video_import_success"><![CDATA[Ihr Video <b>%1$s</b> wurde erfolgreich importiert]]></string>
<string name="peertube_video_import_error"><![CDATA[Der Import Ihres Videos <b>%1$s</b> ist fehlgeschlagen]]></string> <string name="peertube_video_import_error"><![CDATA[Der Import Ihres Videos <b>%1$s</b> ist fehlgeschlagen]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> hat ein neues Video veröffentlicht: <b>%2$s</b>]]></string> <string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> hat ein neues Video veröffentlicht: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Dein Video <b>%1$s</b> wurde gesperrt]]></string> <string name="peertube_video_blacklist"><![CDATA[Dein Video <b>%1$s</b> wurde gesperrt]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Die Sperre für dein Video <b>%1$s</b> wurde aufgehoben]]></string> <string name="peertube_video_unblacklist"><![CDATA[Die Sperre für dein Video <b>%1$s</b> wurde aufgehoben]]></string>
<string name="peertube_video_report_success"><![CDATA[Your abuse report <b>%1$s</b> has been accepted]]></string> <string name="peertube_video_report_success"><![CDATA[Deine Missbrauchs-Meldung <b>%1$s</b> wurde übermittelt]]></string>
<string name="peertube_video_abuse"><![CDATA[Neuer Missbrauchsbericht für Video: <b>%1$s</b>]]></string> <string name="peertube_video_abuse"><![CDATA[Neuer Missbrauchsbericht für Video: <b>%1$s</b>]]></string>
<string name="add_public_comment">Öffentlichen Kommentar hinzufügen</string> <string name="add_public_comment">Öffentlichen Kommentar hinzufügen</string>
<string name="send_comment">Kommentar absenden</string> <string name="send_comment">Kommentar absenden</string>
<string name="all">Alle</string> <string name="all">Alle</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Wiedergabegeschwindigkeit</string>
<string name="normal">Normal</string>
<string name="delete_history">Videoverlauf löschen</string>
<string name="delete_history_confirm">Sind Sie sicher, dass Sie den gesamten Verlauf löschen wollen?</string>
<string name="export_list">Exportieren</string>
<string name="import_list">Importieren</string>
<string name="export_notification_title">Export erfolgreich!</string>
<string name="export_notification_content">Hier tippen, um den Export per E-Mail zu senden</string>
<string name="export_notification_subjet">Neue Wiedergabeliste</string>
<string name="export_notification_body">Die angehängte Datei mit TubeLab öffnen</string>
<string name="playlists">Wiedergabelisten</string> <string name="playlists">Wiedergabelisten</string>
<string name="no_playlist">Keine Wiedergabelisten</string>
<string name="display_name">Anzeigename</string> <string name="display_name">Anzeigename</string>
<string name="action_playlist_add">Sie haben noch keine Wiedergabelisten. Klicken Sie auf das Symbol „➕, um eine neue Wiedergabeliste hinzuzufügen.</string> <string name="action_playlist_add">Sie haben noch keine Wiedergabelisten. Klicken Sie auf das Symbol „➕, um eine neue Wiedergabeliste hinzuzufügen</string>
<string name="error_display_name">Du musst einen Anzeigenamen angeben!</string> <string name="error_display_name">Du musst einen Anzeigenamen angeben!</string>
<string name="error_channel_mandatory">Ein Kanal wird benötigt, wenn es sich um eine öffentliche Wiedergabeliste handelt.</string> <string name="error_channel_mandatory">Ein Kanal wird benötigt, wenn es sich um eine öffentliche Wiedergabeliste handelt.</string>
<string name="action_playlist_create">Wiedergabeliste erstellen</string> <string name="action_playlist_create">Wiedergabeliste erstellen</string>
@ -196,18 +261,19 @@
<string name="password_indicator">Verwende mindestens 8 Zeichen</string> <string name="password_indicator">Verwende mindestens 8 Zeichen</string>
<string name="password_too_short">Das Passwort muss mindestens 8 Zeichen lang sein</string> <string name="password_too_short">Das Passwort muss mindestens 8 Zeichen lang sein</string>
<string name="username_error">Der Benutzername darf nur Buchstaben, Ziffern und Unterstriche enthalten</string> <string name="username_error">Der Benutzername darf nur Buchstaben, Ziffern und Unterstriche enthalten</string>
<string name="account_created">Account erfolgreich erstellt!</string> <string name="account_created">Konto erstellt!</string>
<string name="account_created_message"> Dein Account wurde erfolgreich erstellt!\n\n <string name="account_created_message">Dein Konto wurde erfolgreich erstellt!\n\n
Denke daran, deine E-Mail-Adresse innerhalb der nächsten 48 Stunden zu bestätigen.\n\n Denke daran, deine E-Mail-Adresse innerhalb der nächsten 48 Stunden zu bestätigen.\n\n
Du kannst nun deinen Account verbinden, indem du <b>%1$s</b> in das erste Feld schreibst und auf <b>Verbinden</b>klickst.\n\n Du kannst nun deinen Account verbinden, indem du <b>%1$s</b> in das erste Feld schreibst und auf <b>Verbinden</b>klickst.\n\n
<b>Wichtig</b>: Wenn deine Instanz eine Bestätigung benötigt, erhältst du eine E-Mail, sobald sie geprüft wurde! <b>Wichtig</b>: Wenn deine Instanz eine Bestätigung benötigt, erhältst du eine E-Mail, sobald sie geprüft wurde!
</string> </string>
<string name="account">Account</string> <string name="account">Benutzerkonto</string>
<string name="report_account">Account melden</string> <string name="report_account">Konto melden</string>
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normal</item>
<item>WebView</item> <item>WebView</item>
<item>Direkter Datenstrom</item> <item>Magnet</item>
<item>Direkter Stream</item> <item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Hell</item> <item>Hell</item>
@ -216,7 +282,7 @@
</string-array> </string-array>
<string-array name="settings_video_quality"> <string-array name="settings_video_quality">
<item>Hoch</item> <item>Hoch</item>
<item>Medium</item> <item>Mittel</item>
<item>Niedrig</item> <item>Niedrig</item>
</string-array> </string-array>
<string name="unfollow_confirm">Möchtest du diesem Konto nicht mehr folgen?</string> <string name="unfollow_confirm">Möchtest du diesem Konto nicht mehr folgen?</string>
@ -225,27 +291,27 @@
<string name="agreement_check_peertube">Ich bin mindestens 16 Jahre alt und stimme den %1$s dieser Instanz zu</string> <string name="agreement_check_peertube">Ich bin mindestens 16 Jahre alt und stimme den %1$s dieser Instanz zu</string>
<string name="edit_profile">Profil bearbeiten</string> <string name="edit_profile">Profil bearbeiten</string>
<string name="make_an_action">Aktion ausführen</string> <string name="make_an_action">Aktion ausführen</string>
<string name="action_unfollow">Nicht mehr folgen</string> <string name="action_unfollow">Abonnement abbestellen</string>
<string name="display_nsfw_videos">Heikle Videos anzeigen</string> <string name="display_nsfw_videos">Heikle Videos anzeigen</string>
<string name="fullscreen">Vollbildmodus</string> <string name="fullscreen">Vollbildmodus</string>
<string name="bookmark_peertube_empty">Keine Videos in den Favoriten!</string> <string name="bookmark_peertube_empty">Keine Videos in den Favoriten!</string>
<string name="delete_channel">Kanal entfernen</string> <string name="delete_channel">Kanal entfernen</string>
<string name="action_channel_confirm_delete">Möchtest du diesen Kanal wirklich löschen?</string> <string name="action_channel_confirm_delete">Möchtest du diesen Kanal wirklich löschen?</string>
<string name="modify_playlists">Video in Wiedergabelisten</string> <string name="modify_playlists">Video in Wiedergabelisten</string>
<string name="no_muted">Keine stummgeschalteten Accounts!</string> <string name="no_muted">Keine stummgeschalteten Konten!</string>
<string name="error_display_name_channel">Du musst einen Namen und einen Anzeigenamen für diesen Kanal definieren!</string> <string name="error_display_name_channel">Du musst einen Namen und einen Anzeigenamen für diesen Kanal definieren!</string>
<string name="action_channel_create">Kanal erstellen</string> <string name="action_channel_create">Kanal erstellen</string>
<string name="action_channel_edit">Kanal bearbeiten</string> <string name="action_channel_edit">Kanal bearbeiten</string>
<string name="email_error_domain">E-Mail-Adressen bei %1$s sind nicht erlaubt!</string> <string name="email_error_domain">E-Mail-Adressen bei %1$s sind nicht erlaubt!</string>
<string name="report_comment_size">Bitte gib einen Grund an</string> <string name="report_comment_size">Bitte gib einen Grund an</string>
<string name="not_logged_in">Du musst authentifiziert sein, um diesen Vorgang auszuführen.</string> <string name="not_logged_in">Du musst authentifiziert sein, um diesen Vorgang auszuführen.</string>
<string name="successful_report">Der Account wurde gemeldet!</string> <string name="successful_report">Das Konto wurde gemeldet!</string>
<string name="successful_report_comment">Der Kommentar wurde gemeldet!</string> <string name="successful_report_comment">Der Kommentar wurde gemeldet!</string>
<string name="successful_video_report">Dieses Video wurde gemeldet!</string> <string name="successful_video_report">Dieses Video wurde gemeldet!</string>
<string name="password_length_error">Das Passwort muss mindestens 6 Zeichen lang sein!</string> <string name="password_length_error">Das Passwort muss mindestens 6 Zeichen lang sein!</string>
<string name="muted_done">Der Account wurde stummgeschaltet!</string> <string name="muted_done">Das Konto wurde stummgeschaltet!</string>
<string name="edit_video">Video bearbeiten</string> <string name="edit_video">Video bearbeiten</string>
<string name="create_an_account">Account erstellen</string> <string name="create_an_account">Konto erstellen</string>
<string name="followers_count">%1$s Abonnenten</string> <string name="followers_count">%1$s Abonnenten</string>
<string name="developer">Entwickler</string> <string name="developer">Entwickler</string>
<string name="about_vesrion">Version %1$s</string> <string name="about_vesrion">Version %1$s</string>
@ -263,8 +329,9 @@
<string name="pickup_categories">Kategorien wählen</string> <string name="pickup_categories">Kategorien wählen</string>
<string name="pickup_languages">Sprachen wählen</string> <string name="pickup_languages">Sprachen wählen</string>
<string name="notification_channel_name">Information aktualisiert</string> <string name="notification_channel_name">Information aktualisiert</string>
<string name="add_account">Füge einen Account hinzu</string> <string name="fetch_notification_channel_name">Rufe Benachrichtigungen ab</string>
<string name="list_of_accounts">Liste der Accounts</string> <string name="add_account">Ein Konto hinzufügen</string>
<string name="list_of_accounts">Liste der Konten</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>
<string name="play">Abspielen</string> <string name="play">Abspielen</string>
<string name="minimize">Verkleinern</string> <string name="minimize">Verkleinern</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Προσθήκη δημόσιας απάντησης</string> <string name="add_public_reply">Προσθήκη δημόσιας απάντησης</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d απάντηση</item> <item quantity="one">%d απάντηση</item>
<item quantity="other">%d απαντήσεις</item> <item quantity="other">%d απαντήσεις</item>
@ -38,9 +63,28 @@
<string name="upload_video">Μεταφόρτωση</string> <string name="upload_video">Μεταφόρτωση</string>
<string name="image_preview">Προεπισκόπηση εικόνας</string> <string name="image_preview">Προεπισκόπηση εικόνας</string>
<string name="file_to_upload">Επιλέξτε το αρχείο για μεταφόρτωση</string> <string name="file_to_upload">Επιλέξτε το αρχείο για μεταφόρτωση</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">Κανάλι</string> <string name="channel">Κανάλι</string>
<string name="videos">Βίντεο</string> <string name="videos">Βίντεο</string>
<string name="channels">Κανάλια</string> <string name="channels">Κανάλια</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Ναι</string> <string name="yes">Ναι</string>
<string name="no">Όχι</string> <string name="no">Όχι</string>
<string name="cancel">Ακύρωση</string> <string name="cancel">Ακύρωση</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Κάντε κλικ εδώ για επεξεργασία δεδομένων του βίντεο.</string> <string name="video_uploaded_action">Κάντε κλικ εδώ για επεξεργασία δεδομένων του βίντεο.</string>
<string name="toot_select_image_error">Παρουσιάστηκε κάποιο σφάλμα κατά την επιλογή του πολυμέσου!</string> <string name="toot_select_image_error">Παρουσιάστηκε κάποιο σφάλμα κατά την επιλογή του πολυμέσου!</string>
<string name="download_file">Λήψη του %1$s</string> <string name="download_file">Λήψη του %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">Ιδιωτικότητα</string> <string name="action_privacy">Ιδιωτικότητα</string>
<string name="action_logout">Αποσύνδεση</string> <string name="action_logout">Αποσύνδεση</string>
<string name="login">Σύνδεση</string> <string name="login">Σύνδεση</string>
@ -78,8 +123,15 @@
<string name="toast_error_loading_account">Παρουσιάστηκε κάποιο σφάλμα, κατά την εναλλαγή μεταξύ των λογαριασμών!</string> <string name="toast_error_loading_account">Παρουσιάστηκε κάποιο σφάλμα, κατά την εναλλαγή μεταξύ των λογαριασμών!</string>
<string name="toast_error_search">Παρουσιάστηκε κάποιο σφάλμα κατά την αναζήτηση!</string> <string name="toast_error_search">Παρουσιάστηκε κάποιο σφάλμα κατά την αναζήτηση!</string>
<string name="nothing_to_do">Δεν μπορεί να εκτελεστεί καμία ενέργεια</string> <string name="nothing_to_do">Δεν μπορεί να εκτελεστεί καμία ενέργεια</string>
<string name="action_follow">Ακολούθηση</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Σίγαση</string> <string name="action_mute">Σίγαση</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Αναζήτηση</string> <string name="search">Αναζήτηση</string>
<string name="delete">Διαγραφή</string> <string name="delete">Διαγραφή</string>
<string name="action_lists_confirm_delete">Είστε βέβαιοι ότι θέλετε να διαγράψετε μόνιμα αυτή τη λίστα;</string> <string name="action_lists_confirm_delete">Είστε βέβαιοι ότι θέλετε να διαγράψετε μόνιμα αυτή τη λίστα;</string>
@ -93,6 +145,8 @@
<string name="app_logo">Το λογότυπο της εφαρμογής</string> <string name="app_logo">Το λογότυπο της εφαρμογής</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Συνδρομές</string> <string name="subscriptions">Συνδρομές</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Διαγραφή ενός σχόλιου</string> <string name="delete_comment">Διαγραφή ενός σχόλιου</string>
<string name="delete_comment_confirm">Θέλετε να διαγράψετε αυτό το σχόλιο, στα σίγουρα;</string> <string name="delete_comment_confirm">Θέλετε να διαγράψετε αυτό το σχόλιο, στα σίγουρα;</string>
<string name="set_video_mode">Κατάσταση λειτουργίας για τα βίντεο</string> <string name="set_video_mode">Κατάσταση λειτουργίας για τα βίντεο</string>
@ -177,7 +231,18 @@
<string name="send_comment">Αποστολή σχόλιου</string> <string name="send_comment">Αποστολή σχόλιου</string>
<string name="all">Όλα</string> <string name="all">Όλα</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Λίστες αναπαραγωγής</string> <string name="playlists">Λίστες αναπαραγωγής</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Εμφανιζόμενο όνομα</string> <string name="display_name">Εμφανιζόμενο όνομα</string>
<string name="action_playlist_add">Δεν έχετε καμία λίστα αναπαραγωγής. Κάντε κλικ στο εικονίδιο « + », για να προσθέσετε μία καινούργια λίστα</string> <string name="action_playlist_add">Δεν έχετε καμία λίστα αναπαραγωγής. Κάντε κλικ στο εικονίδιο « + », για να προσθέσετε μία καινούργια λίστα</string>
<string name="error_display_name">Πρέπει να εισάγεται ένα όνομα εμφάνισης!</string> <string name="error_display_name">Πρέπει να εισάγεται ένα όνομα εμφάνισης!</string>
@ -206,7 +271,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Webview</item> <item>Webview</item>
<item>Άμεση ροή</item> <item>Άμεση ροή</item>
<item>Άμεση ροή</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Φωτεινό</item> <item>Φωτεινό</item>
@ -224,7 +290,7 @@
<string name="agreement_check_peertube">Είμαι τουλάχιστον 16 χρονών, και συμφωνώ με %1$s αυτής της υπόστασης</string> <string name="agreement_check_peertube">Είμαι τουλάχιστον 16 χρονών, και συμφωνώ με %1$s αυτής της υπόστασης</string>
<string name="edit_profile">Επεξεργασία προφίλ</string> <string name="edit_profile">Επεξεργασία προφίλ</string>
<string name="make_an_action">Κάντε μια ενέργεια</string> <string name="make_an_action">Κάντε μια ενέργεια</string>
<string name="action_unfollow">Διακοπή παρακολούθησης</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Εμφάνιση ευαίσθητων βίντεο</string> <string name="display_nsfw_videos">Εμφάνιση ευαίσθητων βίντεο</string>
<string name="fullscreen">Πλήρης οθόνη</string> <string name="fullscreen">Πλήρης οθόνη</string>
<string name="bookmark_peertube_empty">Δεν υπάρχουν βίντεο στα αγαπημένα σας!</string> <string name="bookmark_peertube_empty">Δεν υπάρχουν βίντεο στα αγαπημένα σας!</string>
@ -262,6 +328,7 @@
<string name="pickup_categories">Επιλογή κατηγοριών</string> <string name="pickup_categories">Επιλογή κατηγοριών</string>
<string name="pickup_languages">Επιλογή γλωσσών</string> <string name="pickup_languages">Επιλογή γλωσσών</string>
<string name="notification_channel_name">Ενημέρωση πληροφοριών</string> <string name="notification_channel_name">Ενημέρωση πληροφοριών</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Προσθήκη λογαριασμού</string> <string name="add_account">Προσθήκη λογαριασμού</string>
<string name="list_of_accounts">Λίστα λογαριασμών</string> <string name="list_of_accounts">Λίστα λογαριασμών</string>
<string name="pause">Παύση</string> <string name="pause">Παύση</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Añade una respuesta pública</string> <string name="add_public_reply">Añade una respuesta pública</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d respuesta</item> <item quantity="one">%d respuesta</item>
<item quantity="other">%d respuestas</item> <item quantity="other">%d respuestas</item>
@ -38,9 +63,28 @@
<string name="upload_video">Subir</string> <string name="upload_video">Subir</string>
<string name="image_preview">Previsualización de la imagen</string> <string name="image_preview">Previsualización de la imagen</string>
<string name="file_to_upload">Seleccione el archivo a subir</string> <string name="file_to_upload">Seleccione el archivo a subir</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">Canal</string> <string name="channel">Canal</string>
<string name="videos">Vídeos</string> <string name="videos">Vídeos</string>
<string name="channels">Canales</string> <string name="channels">Canales</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes"></string> <string name="yes"></string>
<string name="no">No</string> <string name="no">No</string>
<string name="cancel">Cancelar</string> <string name="cancel">Cancelar</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Pulsa aquí para editar los datos del vídeo.</string> <string name="video_uploaded_action">Pulsa aquí para editar los datos del vídeo.</string>
<string name="toot_select_image_error">¡Ocurrió un error al seleccionar la imagen!</string> <string name="toot_select_image_error">¡Ocurrió un error al seleccionar la imagen!</string>
<string name="download_file">Descargando %1$s</string> <string name="download_file">Descargando %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">Privacidad</string> <string name="action_privacy">Privacidad</string>
<string name="action_logout">Cerrar sesión</string> <string name="action_logout">Cerrar sesión</string>
<string name="login">Iniciar sesión</string> <string name="login">Iniciar sesión</string>
@ -78,8 +123,15 @@
<string name="toast_error_loading_account">¡Ocurrió un error al cambiar de cuentas!</string> <string name="toast_error_loading_account">¡Ocurrió un error al cambiar de cuentas!</string>
<string name="toast_error_search">¡Ocurrió un error durante la búsqueda!</string> <string name="toast_error_search">¡Ocurrió un error durante la búsqueda!</string>
<string name="nothing_to_do">No hay ninguna acción disponible</string> <string name="nothing_to_do">No hay ninguna acción disponible</string>
<string name="action_follow">Seguir</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Silenciar</string> <string name="action_mute">Silenciar</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Buscar</string> <string name="search">Buscar</string>
<string name="delete">Eliminar</string> <string name="delete">Eliminar</string>
<string name="action_lists_confirm_delete">¿Estás seguro de que quieres eliminar definitivamente esta lista?</string> <string name="action_lists_confirm_delete">¿Estás seguro de que quieres eliminar definitivamente esta lista?</string>
@ -93,6 +145,8 @@
<string name="app_logo">Logo de la aplicación</string> <string name="app_logo">Logo de la aplicación</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Suscripciones</string> <string name="subscriptions">Suscripciones</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Eliminar un comentario</string> <string name="delete_comment">Eliminar un comentario</string>
<string name="delete_comment_confirm">¿Realmente deseas eliminar este comentario?</string> <string name="delete_comment_confirm">¿Realmente deseas eliminar este comentario?</string>
<string name="set_video_mode">Aplicar el modo de video</string> <string name="set_video_mode">Aplicar el modo de video</string>
@ -177,7 +231,18 @@
<string name="send_comment">Enviar comentario</string> <string name="send_comment">Enviar comentario</string>
<string name="all">Todo</string> <string name="all">Todo</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Listas de reproducción</string> <string name="playlists">Listas de reproducción</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Nombre para mostrar</string> <string name="display_name">Nombre para mostrar</string>
<string name="action_playlist_add">No tienes ninguna lista de reproducción. Pulsa en el icono \"+\" para añadir una nueva lista</string> <string name="action_playlist_add">No tienes ninguna lista de reproducción. Pulsa en el icono \"+\" para añadir una nueva lista</string>
<string name="error_display_name">¡Debe proporcionar un nombre para mostrar!</string> <string name="error_display_name">¡Debe proporcionar un nombre para mostrar!</string>
@ -207,7 +272,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Webview</item> <item>Webview</item>
<item>Corriente Directa</item> <item>Corriente Directa</item>
<item>Corriente directa</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Luz</item> <item>Luz</item>
@ -225,7 +291,7 @@
<string name="agreement_check_peertube">Tengo por lo menos 16 años y estoy de acuerdo con los %1$s de esta instancia</string> <string name="agreement_check_peertube">Tengo por lo menos 16 años y estoy de acuerdo con los %1$s de esta instancia</string>
<string name="edit_profile">Editar perfil</string> <string name="edit_profile">Editar perfil</string>
<string name="make_an_action">Haga una acción</string> <string name="make_an_action">Haga una acción</string>
<string name="action_unfollow">Unfollow</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Mostrar videos sensibles</string> <string name="display_nsfw_videos">Mostrar videos sensibles</string>
<string name="fullscreen">Pantalla completa</string> <string name="fullscreen">Pantalla completa</string>
<string name="bookmark_peertube_empty">No hay videos en tus favoritos!</string> <string name="bookmark_peertube_empty">No hay videos en tus favoritos!</string>
@ -263,6 +329,7 @@
<string name="pickup_categories">Selecciona una o más categorías</string> <string name="pickup_categories">Selecciona una o más categorías</string>
<string name="pickup_languages">Selecciona uno o más idiomas</string> <string name="pickup_languages">Selecciona uno o más idiomas</string>
<string name="notification_channel_name">Actualizar la información</string> <string name="notification_channel_name">Actualizar la información</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Añadir una cuenta</string> <string name="add_account">Añadir una cuenta</string>
<string name="list_of_accounts">Lista de cuentas</string> <string name="list_of_accounts">Lista de cuentas</string>
<string name="pause">Pausa</string> <string name="pause">Pausa</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_autoplay">Automatic playback</string> <string name="set_video_in_list">Vidéos en liste</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_video_in_list_description">Modifier la mise en page pour afficher les vidéos dans une liste</string>
<string name="set_fullscreen">Fullscreen</string> <string name="no_instances">Aucune instance !</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="show_more">Afficher plus</string>
<string name="show_less">Afficher moins</string>
<string name="set_play_screen_lock">Verrouillage de l\'écran</string>
<string name="set_play_screen_lock_description">Continuer à lire des vidéos quand l\'écran est verrouillé</string>
<string name="save">Enregistrer</string>
<string name="enable_history">Activer l\'historique</string>
<string name="change_profile_picture">Changer la photo de profil</string>
<string name="set_autoplay">Lecture automatique</string>
<string name="set_autoplay_description">Si activé, les vidéos seront lues automatiquement</string>
<string name="set_fullscreen">Plein écran</string>
<string name="set_fullscreen_description">Ouvrir automatiquement les vidéos en plein écran</string>
<string name="set_autoplay_next_video_settings">Lecture auto</string>
<string name="set_autoplay_next_video">Démarrer automatiquement la lecture de la prochaine vidéo</string>
<string name="set_autoplay_next_video_description">Quand une vidéo est finie, continuer avec la prochaine vidéo suggérée.</string>
<string name="add_public_reply">Ajouter une réponse publique</string> <string name="add_public_reply">Ajouter une réponse publique</string>
<string name="originally_published">Publié originalement</string>
<string name="activity">Activité</string>
<string name="app">Appli</string>
<string name="notif_new_video">Nouvelle vidéo de vos abonnements</string>
<string name="notif_new_comment">Nouveau commentaire sur votre vidéo</string>
<string name="notif_blocked">Une de vos vidéos est bloquée/débloquée</string>
<string name="notif_video_published">Vidéo publiée (après transcodage/mise à jour planifiée)</string>
<string name="notif_video_imported">Importation de la vidéo terminée</string>
<string name="notif_new_followers">Vous ou votre/vos chaîne(s) avez un nouvel abonné</string>
<string name="notif_video_mention">Quelqu\'un vous a mentionné·e dans un commentaire</string>
<string name="notif_abuse_received">Un rapport d\'abus a reçu un nouveau message</string>
<string name="notif_abuse_accepted">Un de vos rapports d\'abus a été accepté ou rejeté par les modérateurs</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d réponse</item> <item quantity="one">%d réponse</item>
<item quantity="other">%d réponses</item> <item quantity="other">%d réponses</item>
@ -37,10 +62,29 @@
<string name="close">Fermer</string> <string name="close">Fermer</string>
<string name="upload_video">Téléverser</string> <string name="upload_video">Téléverser</string>
<string name="image_preview">Aperçu de l\'image</string> <string name="image_preview">Aperçu de l\'image</string>
<string name="file_to_upload">Sélectionnez un fichier à transférer</string> <string name="file_to_upload">Sélectionnez un fichier à téléverser</string>
<string name="new_video">Nouvelle vidéo</string>
<string name="new_blacklist">Nouvelles infos sut la liste noire</string>
<string name="new_my_video_published">Votre vidéo est publiée</string>
<string name="new_my_video_error">Erreur lors de la publication de votre vidéo</string>
<string name="new_comment">Nouveau commentaire</string>
<string name="new_follow">Nouvel abonnement</string>
<string name="channel">Chaîne</string> <string name="channel">Chaîne</string>
<string name="videos">Vidéos</string> <string name="videos">Vidéos</string>
<string name="channels">Chaînes</string> <string name="channels">Chaînes</string>
<string name="refresh_every">Récupérer chaque :</string>
<string-array name="refresh_time">
<item>Jamais</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 heure</item>
<item>2 heures</item>
<item>6 heures</item>
<item>12 heures</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Oui</string> <string name="yes">Oui</string>
<string name="no">Non</string> <string name="no">Non</string>
<string name="cancel">Annuler</string> <string name="cancel">Annuler</string>
@ -54,12 +98,13 @@
<string name="date_day">%d j</string> <string name="date_day">%d j</string>
<string name="number_view_video">%s vues</string> <string name="number_view_video">%s vues</string>
<string name="title_instance_login">Domaine de l\'instance</string> <string name="title_instance_login">Domaine de l\'instance</string>
<string name="uploading">Transfert en cours, veuillez patienter </string> <string name="uploading">Téléversement en cours, veuillez patienter…</string>
<string name="upload_video_success">La vidéo a été transférée !</string> <string name="upload_video_success">La vidéo a été téléversée !</string>
<string name="toast_cancelled">Transfert annulé !</string> <string name="toast_cancelled">Téléversement annulé !</string>
<string name="video_uploaded_action">Cliquez ici pour éditer les données de la vidéo.</string> <string name="video_uploaded_action">Cliquez ici pour modifier les données de la vidéo.</string>
<string name="toot_select_image_error">Une erreur sest produite lors de la sélection du média!</string> <string name="toot_select_image_error">Une erreur s\'est produite lors de la sélection du média !</string>
<string name="download_file">Télécharger %1$s</string> <string name="download_file">Télécharger %1$s</string>
<string name="account_updated">Le compte a été mis à jour !</string>
<string name="action_privacy">Confidentialité</string> <string name="action_privacy">Confidentialité</string>
<string name="action_logout">Déconnexion</string> <string name="action_logout">Déconnexion</string>
<string name="login">Connexion</string> <string name="login">Connexion</string>
@ -80,6 +125,13 @@
<string name="nothing_to_do">Aucune action ne peut être réalisée</string> <string name="nothing_to_do">Aucune action ne peut être réalisée</string>
<string name="action_follow">S\'abonner</string> <string name="action_follow">S\'abonner</string>
<string name="action_mute">Mettre en sourdine</string> <string name="action_mute">Mettre en sourdine</string>
<string name="unlimited">Illimité</string>
<string name="mb">Mo</string>
<string name="gb">Go</string>
<string name="total_video_quota">Quota vidéo total</string>
<string name="daily_video_quota">Quota vidéo quotidien</string>
<string name="nsfw_title_warning">Contenu adulte ou vulgaire</string>
<string name="nsfw_message_warning">Cette vidéo contient du contenu adulte ou vulgaire. Êtes-vous sûr·e de vouloir la regarder ?</string>
<string name="search">Chercher</string> <string name="search">Chercher</string>
<string name="delete">Supprimer</string> <string name="delete">Supprimer</string>
<string name="action_lists_confirm_delete">Êtes-vous sûr de vouloir supprimer définitivement cette liste de lecture ?</string> <string name="action_lists_confirm_delete">Êtes-vous sûr de vouloir supprimer définitivement cette liste de lecture ?</string>
@ -93,6 +145,8 @@
<string name="app_logo">Logo de lapplication</string> <string name="app_logo">Logo de lapplication</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Abonnements</string> <string name="subscriptions">Abonnements</string>
<string name="delete_instance">Supprimer l\'instance</string>
<string name="delete_instance_confirm">Êtes-vous sûr·e de vouloir supprimer cette instance ?</string>
<string name="delete_comment">Supprimer le commentaire</string> <string name="delete_comment">Supprimer le commentaire</string>
<string name="delete_comment_confirm">Etes-vous sûr de vouloir supprimer ce commentaire ?</string> <string name="delete_comment_confirm">Etes-vous sûr de vouloir supprimer ce commentaire ?</string>
<string name="set_video_mode">Mode pour les vidéos</string> <string name="set_video_mode">Mode pour les vidéos</string>
@ -133,7 +187,7 @@
<string name="description">Libellé</string> <string name="description">Libellé</string>
<string name="toast_peertube_video_updated">La vidéo a été mise à jour !</string> <string name="toast_peertube_video_updated">La vidéo a été mise à jour !</string>
<string name="register_account">Créer un compte</string> <string name="register_account">Créer un compte</string>
<string name="email_address">Adresse l</string> <string name="email_address">Adresse courriel</string>
<string name="preview">Aperçu</string> <string name="preview">Aperçu</string>
<string name="change_preview">Modifier l\'aperçu</string> <string name="change_preview">Modifier l\'aperçu</string>
<string name="name">Nom</string> <string name="name">Nom</string>
@ -171,13 +225,24 @@
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> a publié une nouvelle vidéo : <b>%2$s</b>]]></string> <string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> a publié une nouvelle vidéo : <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Votre vidéo <b>%1$s</b> a été blacklisté]]></string> <string name="peertube_video_blacklist"><![CDATA[Votre vidéo <b>%1$s</b> a été blacklisté]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Votre vidéo <b>%1$s</b> nest plus blacklisté]]></string> <string name="peertube_video_unblacklist"><![CDATA[Votre vidéo <b>%1$s</b> nest plus blacklisté]]></string>
<string name="peertube_video_report_success"><![CDATA[Your abuse report <b>%1$s</b> has been accepted]]></string> <string name="peertube_video_report_success"><![CDATA[Votre rapport dabus <b>%1$s</b> a été accepté]]></string>
<string name="peertube_video_abuse"><![CDATA[Nouveau signalement pour la vidéo : <b>%1$s</b>]]></string> <string name="peertube_video_abuse"><![CDATA[Nouveau signalement pour la vidéo : <b>%1$s</b>]]></string>
<string name="add_public_comment">Ajouter un commentaire public</string> <string name="add_public_comment">Ajouter un commentaire public</string>
<string name="send_comment">Envoyer un commentaire</string> <string name="send_comment">Envoyer un commentaire</string>
<string name="all">Tout</string> <string name="all">Tout</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Vitesse de lecture</string>
<string name="normal">Normale</string>
<string name="delete_history">Supprimer l\'historique des vidéos</string>
<string name="delete_history_confirm">Êtes-vous sûr·e de vouloir supprimer tout votre historique des vidéos ?</string>
<string name="export_list">Exporter</string>
<string name="import_list">Importer</string>
<string name="export_notification_title">Exportation réussie !</string>
<string name="export_notification_content">Appuyez ici pour envoyer l\'exportation par courriel</string>
<string name="export_notification_subjet">Nouvelle liste de lecture</string>
<string name="export_notification_body">Ouvrir le fichier joint avec TubeLab</string>
<string name="playlists">Listes de lecture</string> <string name="playlists">Listes de lecture</string>
<string name="no_playlist">Aucune liste de lecture</string>
<string name="display_name">Nom d\'affichage</string> <string name="display_name">Nom d\'affichage</string>
<string name="action_playlist_add">Vous n\'avez aucune liste de lecture. Cliquez sur l\'icône « + » pour en ajouter une</string> <string name="action_playlist_add">Vous n\'avez aucune liste de lecture. Cliquez sur l\'icône « + » pour en ajouter une</string>
<string name="error_display_name">Vous devez fournir un nom d\'affichage !</string> <string name="error_display_name">Vous devez fournir un nom d\'affichage !</string>
@ -191,19 +256,24 @@
<string name="sign_up">Sinscrire</string> <string name="sign_up">Sinscrire</string>
<string name="all_field_filled">Veuillez remplir tous les champs !</string> <string name="all_field_filled">Veuillez remplir tous les champs !</string>
<string name="password_error">Les mots de passe ne sont pas identiques !</string> <string name="password_error">Les mots de passe ne sont pas identiques !</string>
<string name="email_error">L\'e-mail ne semble pas être valide !</string> <string name="email_error">Le courriel ne semble pas être valide !</string>
<string name="email_indicator">Vous recevrez un e-mail de confirmation</string> <string name="email_indicator">Vous recevrez un courriel de confirmation</string>
<string name="password_indicator">Utilisez au moins 8 caractères</string> <string name="password_indicator">Utilisez au moins 8 caractères</string>
<string name="password_too_short">Le mot de passe doit contenir au moins 8 caractères</string> <string name="password_too_short">Le mot de passe doit contenir au moins 8 caractères</string>
<string name="username_error">Le nom d\'utilisateur·rice doit être en minuscule, contenir uniquement des lettres, des chiffres, des points et des caractères de soulignement</string> <string name="username_error">Le nom d\'utilisateur·rice doit être en minuscule, contenir uniquement des lettres, des chiffres, des points et des caractères de soulignement</string>
<string name="account_created">Compte créé !</string> <string name="account_created">Compte créé !</string>
<string name="account_created_message">Votre compte est créé !\n\nVous allez recevoir un email de confirmation à l\'adresse <b>%1$s</b>.\n\nCliquez sur le lien présent dans le mail pour valider votre compte.</string> <string name="account_created_message"> Votre compte a été créé !\n\n
Pensez à valider votre courriel dans les 48 heures qui suivent.\n\n
Vous pouvez maintenant connecter votre compte en écrivant <b>%1$s</b> dans le premier champ et en appuyant sur <b>Connecter</b>.\n\n
<b>Important</b> : si votre instance a besoin de validation, vous recevrez un courriel une qu\'elle est fois validée !
</string>
<string name="account">Compte</string> <string name="account">Compte</string>
<string name="report_account">Signaler le compte</string> <string name="report_account">Signaler le compte</string>
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normal</item> <item>Normal</item>
<item>Streaming</item> <item>Streaming</item>
<item>Flux direct</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Lumière</item> <item>Lumière</item>
@ -232,7 +302,7 @@
<string name="error_display_name_channel">Vous devez fournir un nom d\'affichage et un nom pour la chaîne!</string> <string name="error_display_name_channel">Vous devez fournir un nom d\'affichage et un nom pour la chaîne!</string>
<string name="action_channel_create">Créer une chaîne</string> <string name="action_channel_create">Créer une chaîne</string>
<string name="action_channel_edit">Modifier une chaîne</string> <string name="action_channel_edit">Modifier une chaîne</string>
<string name="email_error_domain">Les adresses mails %1$s ne sont pas autorisées !</string> <string name="email_error_domain">Les adresses courriel %1$s ne sont pas autorisées !</string>
<string name="report_comment_size">Veuillez préciser les raisons.</string> <string name="report_comment_size">Veuillez préciser les raisons.</string>
<string name="not_logged_in">Vous devez être connecté.e pour effectuer cette action !</string> <string name="not_logged_in">Vous devez être connecté.e pour effectuer cette action !</string>
<string name="successful_report">Le compte a été signalé !</string> <string name="successful_report">Le compte a été signalé !</string>
@ -259,6 +329,7 @@
<string name="pickup_categories">Sélection des catégories</string> <string name="pickup_categories">Sélection des catégories</string>
<string name="pickup_languages">Sélection des langues</string> <string name="pickup_languages">Sélection des langues</string>
<string name="notification_channel_name">Mise à jour des informations</string> <string name="notification_channel_name">Mise à jour des informations</string>
<string name="fetch_notification_channel_name">Récupérer les notifications</string>
<string name="add_account">Ajouter un compte</string> <string name="add_account">Ajouter un compte</string>
<string name="list_of_accounts">Liste des comptes</string> <string name="list_of_accounts">Liste des comptes</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_autoplay">Automatic playback</string> <string name="set_video_in_list">Elenco di video</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_video_in_list_description">Cambia la disposizione per visualizzare i video in un elenco</string>
<string name="set_fullscreen">Fullscreen</string> <string name="no_instances">Nessuna istanza!</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="show_more">Mostra di più</string>
<string name="show_less">Mostra meno</string>
<string name="set_play_screen_lock">Blocco schermo</string>
<string name="set_play_screen_lock_description">Mantieni la riproduzione dei video quando lo schermo è bloccato</string>
<string name="save">Salva</string>
<string name="enable_history">Abilita la cronologia</string>
<string name="change_profile_picture">Cambia l\'immagine profilo</string>
<string name="set_autoplay">Riproduzione automatica</string>
<string name="set_autoplay_description">Se abilitata, i video verranno riprodotti automaticamente</string>
<string name="set_fullscreen">Schermo intero</string>
<string name="set_fullscreen_description">Apri automaticamente i video a schermo intero</string>
<string name="set_autoplay_next_video_settings">Riproduzione automatica</string>
<string name="set_autoplay_next_video">Inizia automaticamente a riprodurre il video successivo</string>
<string name="set_autoplay_next_video_description">Quando un video finisce, continuare con il video successivo suggerito.</string>
<string name="add_public_reply">Aggiungere una risposta pubblica</string> <string name="add_public_reply">Aggiungere una risposta pubblica</string>
<string name="originally_published">Originariamente pubblicato</string>
<string name="activity">Attività</string>
<string name="app">Applicazione</string>
<string name="notif_new_video">Nuovo video dalle tue sottoscrizioni</string>
<string name="notif_new_comment">Nuovo commento sul tuo video</string>
<string name="notif_blocked">Uno dei tuoi video è bloccato/sbloccato</string>
<string name="notif_video_published">Video pubblicato (dopo la transcodifica/l\'aggiornamento programmato)</string>
<string name="notif_video_imported">Importazione video terminata</string>
<string name="notif_new_followers">Tu o i tuoi canali avete un nuovo abbonamento</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d risposta</item> <item quantity="one">%d risposta</item>
<item quantity="other">%d risposte</item> <item quantity="other">%d risposte</item>
@ -38,9 +63,28 @@
<string name="upload_video">Carica</string> <string name="upload_video">Carica</string>
<string name="image_preview">Anteprima immagine</string> <string name="image_preview">Anteprima immagine</string>
<string name="file_to_upload">Seleziona il file da caricare</string> <string name="file_to_upload">Seleziona il file da caricare</string>
<string name="new_video">Nuovo video</string>
<string name="new_blacklist">Nuove informazioni lista nera</string>
<string name="new_my_video_published">Il tuo video è stato pubblicato</string>
<string name="new_my_video_error">Errore durante la pubblicazione del video</string>
<string name="new_comment">Nuovo commento</string>
<string name="new_follow">Una nuova persona ti segue</string>
<string name="channel">Canale</string> <string name="channel">Canale</string>
<string name="videos">Video</string> <string name="videos">Video</string>
<string name="channels">Canali</string> <string name="channels">Canali</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Mai</item>
<item>15 minuti</item>
<item>30 minuti</item>
<item>1 ora</item>
<item>2 ore</item>
<item>6 ore</item>
<item>12 ore</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Si</string> <string name="yes">Si</string>
<string name="no">No</string> <string name="no">No</string>
<string name="cancel">Annulla</string> <string name="cancel">Annulla</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Premi qui per modificare i dati del video.</string> <string name="video_uploaded_action">Premi qui per modificare i dati del video.</string>
<string name="toot_select_image_error">Si è verificato un errore durante la selezione del archivio!</string> <string name="toot_select_image_error">Si è verificato un errore durante la selezione del archivio!</string>
<string name="download_file">Scarica %1$s</string> <string name="download_file">Scarica %1$s</string>
<string name="account_updated">L\'account è stato aggiornato!</string>
<string name="action_privacy">Privacy</string> <string name="action_privacy">Privacy</string>
<string name="action_logout">Disconnettiti</string> <string name="action_logout">Disconnettiti</string>
<string name="login">Accedi</string> <string name="login">Accedi</string>
@ -71,15 +116,22 @@
<string name="shared_via">Condiviso tramite TubeLab</string> <string name="shared_via">Condiviso tramite TubeLab</string>
<string name="username">Nome utente</string> <string name="username">Nome utente</string>
<string name="settings">Impostazioni</string> <string name="settings">Impostazioni</string>
<string name="logout_account_confirmation">Sei sicuro di voler fare il logout @%1$s@%2$s?</string> <string name="logout_account_confirmation">Sei sicuro/a di voler uscire di @%1$s@%2$s?</string>
<string name="following">Seguendo</string> <string name="following">Seguendo</string>
<string name="followers">Seguaci</string> <string name="followers">Seguaci</string>
<string name="client_error">Impossibile ottenere il client id!</string> <string name="client_error">Impossibile ottenere il client id!</string>
<string name="toast_error_loading_account">Si è verificato un errore durante il cambio tra gli account!</string> <string name="toast_error_loading_account">Si è verificato un errore durante il cambio tra gli account!</string>
<string name="toast_error_search">Si è verificato un errore durante la ricerca!</string> <string name="toast_error_search">Si è verificato un errore durante la ricerca!</string>
<string name="nothing_to_do">Nessuna azione può essere intrapresa</string> <string name="nothing_to_do">Nessuna azione può essere intrapresa</string>
<string name="action_follow">Segui</string> <string name="action_follow">Iscriviti</string>
<string name="action_mute">Silenzia</string> <string name="action_mute">Silenzia</string>
<string name="unlimited">Illimitato</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Cerca</string> <string name="search">Cerca</string>
<string name="delete">Elimina</string> <string name="delete">Elimina</string>
<string name="action_lists_confirm_delete">Sei sicuro di voler eliminare definitivamente questa lista?</string> <string name="action_lists_confirm_delete">Sei sicuro di voler eliminare definitivamente questa lista?</string>
@ -93,6 +145,8 @@
<string name="app_logo">Logo dell\'applicazione</string> <string name="app_logo">Logo dell\'applicazione</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Abbonamenti</string> <string name="subscriptions">Abbonamenti</string>
<string name="delete_instance">Elimina un\'istanza</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Elimina il commento</string> <string name="delete_comment">Elimina il commento</string>
<string name="delete_comment_confirm">Sei sicuro di voler eliminare questo commento?</string> <string name="delete_comment_confirm">Sei sicuro di voler eliminare questo commento?</string>
<string name="set_video_mode">Modalità per i video</string> <string name="set_video_mode">Modalità per i video</string>
@ -177,7 +231,18 @@
<string name="send_comment">Invia commento</string> <string name="send_comment">Invia commento</string>
<string name="all">Tutto</string> <string name="all">Tutto</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normale</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">Nuova playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Playlist</string> <string name="playlists">Playlist</string>
<string name="no_playlist">Nessuna playlist</string>
<string name="display_name">Nome visualizzato</string> <string name="display_name">Nome visualizzato</string>
<string name="action_playlist_add">Non hai nessuna playlist. Premi l\'icona \"+\" per aggiungere una nuova playlist</string> <string name="action_playlist_add">Non hai nessuna playlist. Premi l\'icona \"+\" per aggiungere una nuova playlist</string>
<string name="error_display_name">È necessario fornire un nome da visualizzare!</string> <string name="error_display_name">È necessario fornire un nome da visualizzare!</string>
@ -207,7 +272,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Webview</item> <item>Webview</item>
<item>Stream diretto</item> <item>Stream diretto</item>
<item>Flusso diretto</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Luce</item> <item>Luce</item>
@ -225,7 +291,7 @@
<string name="agreement_check_peertube">Ho almeno 16 anni e accetto le %1$s di questa istanza</string> <string name="agreement_check_peertube">Ho almeno 16 anni e accetto le %1$s di questa istanza</string>
<string name="edit_profile">Modifica profilo</string> <string name="edit_profile">Modifica profilo</string>
<string name="make_an_action">Scegli un\'azione</string> <string name="make_an_action">Scegli un\'azione</string>
<string name="action_unfollow">Smetti di seguire</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Mostra video sensibili</string> <string name="display_nsfw_videos">Mostra video sensibili</string>
<string name="fullscreen">A tutto schermo</string> <string name="fullscreen">A tutto schermo</string>
<string name="bookmark_peertube_empty">Non c\'è nessun video nei tuoi favoriti!</string> <string name="bookmark_peertube_empty">Non c\'è nessun video nei tuoi favoriti!</string>
@ -263,6 +329,7 @@
<string name="pickup_categories">Selezionare categorie</string> <string name="pickup_categories">Selezionare categorie</string>
<string name="pickup_languages">Scegliere le lingue</string> <string name="pickup_languages">Scegliere le lingue</string>
<string name="notification_channel_name">Aggiorna informazioni</string> <string name="notification_channel_name">Aggiorna informazioni</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Aggiungi un account</string> <string name="add_account">Aggiungi un account</string>
<string name="list_of_accounts">Lista di account</string> <string name="list_of_accounts">Lista di account</string>
<string name="pause">Pausa</string> <string name="pause">Pausa</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="other">%d が返信</item> <item quantity="other">%d が返信</item>
</plurals> </plurals>
@ -37,9 +62,28 @@
<string name="upload_video">アップロード</string> <string name="upload_video">アップロード</string>
<string name="image_preview">画像のプレビュー</string> <string name="image_preview">画像のプレビュー</string>
<string name="file_to_upload">アップロードするファイルを選択する</string> <string name="file_to_upload">アップロードするファイルを選択する</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">チャンネル</string> <string name="channel">チャンネル</string>
<string name="videos">動画</string> <string name="videos">動画</string>
<string name="channels">チャンネル</string> <string name="channels">チャンネル</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">はい</string> <string name="yes">はい</string>
<string name="no">いいえ</string> <string name="no">いいえ</string>
<string name="cancel">キャンセル</string> <string name="cancel">キャンセル</string>
@ -59,6 +103,7 @@
<string name="video_uploaded_action">タップして動画情報を編集します。</string> <string name="video_uploaded_action">タップして動画情報を編集します。</string>
<string name="toot_select_image_error">メディアの選択中にエラーが発生しました!</string> <string name="toot_select_image_error">メディアの選択中にエラーが発生しました!</string>
<string name="download_file">ダウンロード: %1$s</string> <string name="download_file">ダウンロード: %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">プライバシー</string> <string name="action_privacy">プライバシー</string>
<string name="action_logout">ログアウト</string> <string name="action_logout">ログアウト</string>
<string name="login">ログイン</string> <string name="login">ログイン</string>
@ -77,8 +122,15 @@
<string name="toast_error_loading_account">アカウントの切り替え中にエラーが発生しました!</string> <string name="toast_error_loading_account">アカウントの切り替え中にエラーが発生しました!</string>
<string name="toast_error_search">検索中にエラーが発生しました!</string> <string name="toast_error_search">検索中にエラーが発生しました!</string>
<string name="nothing_to_do">何もすることはできません</string> <string name="nothing_to_do">何もすることはできません</string>
<string name="action_follow">フォローする</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">ミュート</string> <string name="action_mute">ミュート</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">検索</string> <string name="search">検索</string>
<string name="delete">削除</string> <string name="delete">削除</string>
<string name="action_lists_confirm_delete">このリストを完全に削除してもよろしいですか?</string> <string name="action_lists_confirm_delete">このリストを完全に削除してもよろしいですか?</string>
@ -92,6 +144,8 @@
<string name="app_logo">アプリケーションのロゴ</string> <string name="app_logo">アプリケーションのロゴ</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">サブスクリプション</string> <string name="subscriptions">サブスクリプション</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">コメントを削除</string> <string name="delete_comment">コメントを削除</string>
<string name="delete_comment_confirm">このコメントを削除しますか?</string> <string name="delete_comment_confirm">このコメントを削除しますか?</string>
<string name="set_video_mode">動画のモード</string> <string name="set_video_mode">動画のモード</string>
@ -176,7 +230,18 @@
<string name="send_comment">コメントを送信</string> <string name="send_comment">コメントを送信</string>
<string name="all">すべて</string> <string name="all">すべて</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">プレイリスト</string> <string name="playlists">プレイリスト</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">表示名</string> <string name="display_name">表示名</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">表示名を入力する必要があります!</string> <string name="error_display_name">表示名を入力する必要があります!</string>
@ -206,7 +271,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>標準</item> <item>標準</item>
<item>WebView</item> <item>WebView</item>
<item>ダイレクトストリーム</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>ライト</item> <item>ライト</item>
@ -224,7 +290,7 @@
<string name="agreement_check_peertube">私は16歳以上で、インスタンスの %1$s に同意します。</string> <string name="agreement_check_peertube">私は16歳以上で、インスタンスの %1$s に同意します。</string>
<string name="edit_profile">プロフィールを編集</string> <string name="edit_profile">プロフィールを編集</string>
<string name="make_an_action">アクションを作成</string> <string name="make_an_action">アクションを作成</string>
<string name="action_unfollow">フォロー解除</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -262,6 +328,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">アカウントを追加</string> <string name="add_account">アカウントを追加</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="other">답글 %d개</item> <item quantity="other">답글 %d개</item>
</plurals> </plurals>
@ -37,9 +62,28 @@
<string name="upload_video">Upload</string> <string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string> <string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string> <string name="file_to_upload">Select the file to upload</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">채널</string> <string name="channel">채널</string>
<string name="videos">동영상</string> <string name="videos">동영상</string>
<string name="channels">채널</string> <string name="channels">채널</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes"></string> <string name="yes"></string>
<string name="no">아니</string> <string name="no">아니</string>
<string name="cancel">취소</string> <string name="cancel">취소</string>
@ -59,6 +103,7 @@
<string name="video_uploaded_action">Tap here to edit the video data.</string> <string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">미디어를 선택하는 도중 오류가 발생하였습니다!</string> <string name="toot_select_image_error">미디어를 선택하는 도중 오류가 발생하였습니다!</string>
<string name="download_file">다운로드 %1$s</string> <string name="download_file">다운로드 %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">개인정보</string> <string name="action_privacy">개인정보</string>
<string name="action_logout">로그아웃</string> <string name="action_logout">로그아웃</string>
<string name="login">로그인</string> <string name="login">로그인</string>
@ -77,8 +122,15 @@
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string> <string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string> <string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">아무 조치를 취할 수 없습니다</string> <string name="nothing_to_do">아무 조치를 취할 수 없습니다</string>
<string name="action_follow">팔로우</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">뮤트</string> <string name="action_mute">뮤트</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">검색</string> <string name="search">검색</string>
<string name="delete">삭제</string> <string name="delete">삭제</string>
<string name="action_lists_confirm_delete">이 리스트를 정말로 영원히 삭제하시겠습니까?</string> <string name="action_lists_confirm_delete">이 리스트를 정말로 영원히 삭제하시겠습니까?</string>
@ -92,6 +144,8 @@
<string name="app_logo">응용프로그램 로고</string> <string name="app_logo">응용프로그램 로고</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Subscriptions</string> <string name="subscriptions">Subscriptions</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Delete a comment</string> <string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string> <string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string> <string name="set_video_mode">Mode for videos</string>
@ -176,7 +230,18 @@
<string name="send_comment">댓글 보내기</string> <string name="send_comment">댓글 보내기</string>
<string name="all">모두</string> <string name="all">모두</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">재생목록</string> <string name="playlists">재생목록</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">표시되는 이름</string> <string name="display_name">표시되는 이름</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string> <string name="error_display_name">You must provide a display name!</string>
@ -206,7 +271,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>보통</item> <item>보통</item>
<item>Webview</item> <item>Webview</item>
<item>Direct stream</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>밝음</item> <item>밝음</item>
@ -224,7 +290,7 @@
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string> <string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">프로필 수정</string> <string name="edit_profile">프로필 수정</string>
<string name="make_an_action">Make an action</string> <string name="make_an_action">Make an action</string>
<string name="action_unfollow">언팔로우</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -262,6 +328,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">계정 추가</string> <string name="add_account">계정 추가</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_autoplay">Automatic playback</string> <string name="set_video_in_list">Video lijst</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_video_in_list_description">Wijzig de lay-out voor het weergeven van video\'s in een lijst</string>
<string name="set_fullscreen">Fullscreen</string> <string name="no_instances">Geen instanties !</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="show_more">Meer weergeven</string>
<string name="show_less">Minder weergeven</string>
<string name="set_play_screen_lock">Schermvergrendeling</string>
<string name="set_play_screen_lock_description">Video\'s laten doorspelen terwijl het scherm vergrendeld is</string>
<string name="save">Opslaan</string>
<string name="enable_history">Geschiedenis inschakelen</string>
<string name="change_profile_picture">Profielfoto wijzigen</string>
<string name="set_autoplay">Automatisch afspelen</string>
<string name="set_autoplay_description">Als deze optie is ingeschakeld, worden de video\'s automatisch afgespeeld</string>
<string name="set_fullscreen">Volledig scherm</string>
<string name="set_fullscreen_description">Video\'s automatisch openen op volledig scherm</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">De volgende video automatisch afspelen</string>
<string name="set_autoplay_next_video_description">Wanneer een video eindigt, begin dan met de volgende voorgestelde video.</string>
<string name="add_public_reply">Voeg een openbaar antwoord toe</string> <string name="add_public_reply">Voeg een openbaar antwoord toe</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activiteit</string>
<string name="app">App</string>
<string name="notif_new_video">Nieuwe video uit uw abonnementen</string>
<string name="notif_new_comment">Nieuwe reactie op je video</string>
<string name="notif_blocked">Een van je video\'s is geblokkeerd/gedeblokkeerd</string>
<string name="notif_video_published">Video gepubliceerd (na transcoderen/geplande update)</string>
<string name="notif_video_imported">Video import voltooid</string>
<string name="notif_new_followers">U of één van uw kanalen heeft een nieuwe volger</string>
<string name="notif_video_mention">Iemand heeft je genoemd in een reactie op een video</string>
<string name="notif_abuse_received">Een misbruik rapport heeft een nieuw bericht ontvangen</string>
<string name="notif_abuse_accepted">Een van uw misbruikmeldingen is geaccepteerd of afgewezen door de moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d antwoord</item> <item quantity="one">%d antwoord</item>
<item quantity="other">%d reacties</item> <item quantity="other">%d reacties</item>
@ -38,9 +63,28 @@
<string name="upload_video">Uploaden</string> <string name="upload_video">Uploaden</string>
<string name="image_preview">Beeld preview</string> <string name="image_preview">Beeld preview</string>
<string name="file_to_upload">Selecteer het te uploaden bestand</string> <string name="file_to_upload">Selecteer het te uploaden bestand</string>
<string name="new_video">Nieuwe video</string>
<string name="new_blacklist">Nieuwe blacklist informatie</string>
<string name="new_my_video_published">Je video is gepubliceerd</string>
<string name="new_my_video_error">Fout bij het publiceren van je video</string>
<string name="new_comment">Nieuwe reactie</string>
<string name="new_follow">Nieuwe volger</string>
<string name="channel">Kanaal</string> <string name="channel">Kanaal</string>
<string name="videos">Video\'s</string> <string name="videos">Video\'s</string>
<string name="channels">Kanalen</string> <string name="channels">Kanalen</string>
<string name="refresh_every">Ververs elke:</string>
<string-array name="refresh_time">
<item>Nooit</item>
<item>15 minuten</item>
<item>30 minuten</item>
<item>1 uur</item>
<item>2 uren</item>
<item>6 uren</item>
<item>12 uren</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Ja</string> <string name="yes">Ja</string>
<string name="no">Geen</string> <string name="no">Geen</string>
<string name="cancel">Annuleren</string> <string name="cancel">Annuleren</string>
@ -52,7 +96,7 @@
<string name="date_minutes">%d m</string> <string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string> <string name="date_hours">%d h</string>
<string name="date_day">%d d</string> <string name="date_day">%d d</string>
<string name="number_view_video">%s aanzichten</string> <string name="number_view_video">%s weergaven</string>
<string name="title_instance_login">Instantie host</string> <string name="title_instance_login">Instantie host</string>
<string name="uploading">Uploaden, wacht even…</string> <string name="uploading">Uploaden, wacht even…</string>
<string name="upload_video_success">De video is geüpload!</string> <string name="upload_video_success">De video is geüpload!</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Tik hier om de videogegevens te bewerken.</string> <string name="video_uploaded_action">Tik hier om de videogegevens te bewerken.</string>
<string name="toot_select_image_error">Er is een fout opgetreden bij het selecteren van de media!</string> <string name="toot_select_image_error">Er is een fout opgetreden bij het selecteren van de media!</string>
<string name="download_file">Download %1$s</string> <string name="download_file">Download %1$s</string>
<string name="account_updated">Het account is bijgewerkt!</string>
<string name="action_privacy">Privacy</string> <string name="action_privacy">Privacy</string>
<string name="action_logout">Uitloggen</string> <string name="action_logout">Uitloggen</string>
<string name="login">Inloggen</string> <string name="login">Inloggen</string>
@ -78,14 +123,21 @@
<string name="toast_error_loading_account">Er is een fout opgetreden bij het wisselen tussen de accounts!</string> <string name="toast_error_loading_account">Er is een fout opgetreden bij het wisselen tussen de accounts!</string>
<string name="toast_error_search">Er is een fout opgetreden tijdens het zoeken!</string> <string name="toast_error_search">Er is een fout opgetreden tijdens het zoeken!</string>
<string name="nothing_to_do">Er kan geen actie worden ondernomen</string> <string name="nothing_to_do">Er kan geen actie worden ondernomen</string>
<string name="action_follow">Volg</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Stomme</string> <string name="action_mute">Stomme</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Zoek</string> <string name="search">Zoek</string>
<string name="delete">Verwijder</string> <string name="delete">Verwijder</string>
<string name="action_lists_confirm_delete">Weet u zeker dat u deze lijst permanent wilt verwijderen?</string> <string name="action_lists_confirm_delete">Weet u zeker dat u deze lijst permanent wilt verwijderen?</string>
<string name="action_lists_delete">Lijst verwijderen</string> <string name="action_lists_delete">Lijst verwijderen</string>
<string name="no_comments">Laat als eerste een reactie achter op deze video met de knop rechtsboven!</string> <string name="no_comments">Laat als eerste een reactie achter op deze video met de knop rechtsboven!</string>
<string name="comment_no_allowed_peertube">Commentaar is niet ingeschakeld op deze video!</string> <string name="comment_no_allowed_peertube">Reacties zijn niet ingeschakeld op deze video!</string>
<string name="pickup_resolution">Neem een resolutie op</string> <string name="pickup_resolution">Neem een resolutie op</string>
<string name="bookmark_add_peertube">De video is toegevoegd aan de bladwijzers!</string> <string name="bookmark_add_peertube">De video is toegevoegd aan de bladwijzers!</string>
<string name="bookmark_remove_peertube">De video is uit de bladwijzers verwijderd!</string> <string name="bookmark_remove_peertube">De video is uit de bladwijzers verwijderd!</string>
@ -93,8 +145,10 @@
<string name="app_logo">Logo van de applicatie</string> <string name="app_logo">Logo van de applicatie</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Abonnementen</string> <string name="subscriptions">Abonnementen</string>
<string name="delete_instance">Een instantie vewijderen</string>
<string name="delete_instance_confirm">Weet u zeker dat u deze instantie wilt verijderen?</string>
<string name="delete_comment">Een opmerking verwijderen</string> <string name="delete_comment">Een opmerking verwijderen</string>
<string name="delete_comment_confirm">Weet u zeker dat u deze opmerking wilt verwijderen?</string> <string name="delete_comment_confirm">Weet u zeker dat u deze reactie wilt verwijderen?</string>
<string name="set_video_mode">Modus voor video\'s</string> <string name="set_video_mode">Modus voor video\'s</string>
<string name="filter">Filter</string> <string name="filter">Filter</string>
<string name="sepia_search">Sepia zoeken</string> <string name="sepia_search">Sepia zoeken</string>
@ -116,7 +170,7 @@
<string name="one_of_these_tags">Een van deze tags</string> <string name="one_of_these_tags">Een van deze tags</string>
<string name="apply_filter">Filter toepassen</string> <string name="apply_filter">Filter toepassen</string>
<string-array name="sort_by_array"> <string-array name="sort_by_array">
<item>Beste wedstrijd</item> <item>Beste overeenkomst</item>
<item>Meest recente</item> <item>Meest recente</item>
<item>Minst recent</item> <item>Minst recent</item>
</string-array> </string-array>
@ -157,7 +211,7 @@
<string name="none">Geen</string> <string name="none">Geen</string>
<string name="set_video_mode_description">Maakt het mogelijk om van modus te veranderen voor het afspelen van video\'s (standaard, streaming of via een browser).</string> <string name="set_video_mode_description">Maakt het mogelijk om van modus te veranderen voor het afspelen van video\'s (standaard, streaming of via een browser).</string>
<string name="delete_account_comment">Account opmerkingen verwijderen</string> <string name="delete_account_comment">Account opmerkingen verwijderen</string>
<string name="delete_account_comment_confirm">Weet u zeker dat u alle opmerkingen van dit account wilt verwijderen?</string> <string name="delete_account_comment_confirm">Weet u zeker dat u alle reacties van dit account wilt verwijderen?</string>
<string name="delete_video">Video verwijderen</string> <string name="delete_video">Video verwijderen</string>
<string name="delete_video_confirmation">Weet u zeker dat u deze video wilt verwijderen?</string> <string name="delete_video_confirmation">Weet u zeker dat u deze video wilt verwijderen?</string>
<string name="no_video_to_display">Geen video\'s te tonen!</string> <string name="no_video_to_display">Geen video\'s te tonen!</string>
@ -171,13 +225,24 @@
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> publiceerde een nieuwe video: <b>%2$s</b>]]></string> <string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> publiceerde een nieuwe video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Uw video <b>%1$s</b> is op de zwarte lijst geplaatst]]></string> <string name="peertube_video_blacklist"><![CDATA[Uw video <b>%1$s</b> is op de zwarte lijst geplaatst]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Uw video <b>%1$s</b> is niet op de zwarte lijst gezet]]></string> <string name="peertube_video_unblacklist"><![CDATA[Uw video <b>%1$s</b> is niet op de zwarte lijst gezet]]></string>
<string name="peertube_video_report_success"><![CDATA[Your abuse report <b>%1$s</b> has been accepted]]></string> <string name="peertube_video_report_success"><![CDATA[Uw misbruik melding <b>%1$s</b> is geaccepteerd]]></string>
<string name="peertube_video_abuse"><![CDATA[Nieuw misbruikrapport voor video: <b>%1$s</b>]]></string> <string name="peertube_video_abuse"><![CDATA[Nieuw misbruikrapport voor video: <b>%1$s</b>]]></string>
<string name="add_public_comment">Voeg een publieke opmerking toe</string> <string name="add_public_comment">Voeg een publieke opmerking toe</string>
<string name="send_comment">Stuur commentaar</string> <string name="send_comment">Reactie versturen</string>
<string name="all">Allemaal</string> <string name="all">Allemaal</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Exporteren</string>
<string name="import_list">Importeren</string>
<string name="export_notification_title">Export succesvol!</string>
<string name="export_notification_content">Klik hier om de export per email te versturen</string>
<string name="export_notification_subjet">Nieuwe afspeellijst</string>
<string name="export_notification_body">Open het bijgevoegde bestand met TubeLab</string>
<string name="playlists">Afspeellijsten</string> <string name="playlists">Afspeellijsten</string>
<string name="no_playlist">Geen afspeellijst</string>
<string name="display_name">Weergave naam</string> <string name="display_name">Weergave naam</string>
<string name="action_playlist_add">Je hebt geen afspeellijsten. Tik op het \"+\"-pictogram om een nieuwe afspeellijst toe te voegen</string> <string name="action_playlist_add">Je hebt geen afspeellijsten. Tik op het \"+\"-pictogram om een nieuwe afspeellijst toe te voegen</string>
<string name="error_display_name">U moet een displaynaam opgeven!</string> <string name="error_display_name">U moet een displaynaam opgeven!</string>
@ -202,12 +267,13 @@
U kunt nu verbinding maken met uw account door <b>%1$s</b> in het eerste veld te schrijven en op <b>Verbinden</b>te klikken.\n\n U kunt nu verbinding maken met uw account door <b>%1$s</b> in het eerste veld te schrijven en op <b>Verbinden</b>te klikken.\n\n
<b>Belangrijke</b>: Als je instantie validatie vereist, je ontvangt een e-mail zodra deze is gevalideerd! <b>Belangrijke</b>: Als je instantie validatie vereist, je ontvangt een e-mail zodra deze is gevalideerd!
</string> </string>
<string name="account">Rekening</string> <string name="account">Account</string>
<string name="report_account">Rapportageformulier</string> <string name="report_account">Account rapporteren</string>
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Webview</item> <item>Webview</item>
<item>Directe stroom</item> <item>Directe stroom</item>
<item>Rechtstreeks gegevensstroom</item> <item>Magneetlink</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Licht</item> <item>Licht</item>
@ -219,31 +285,31 @@
<item>Gemiddeld</item> <item>Gemiddeld</item>
<item>Laag</item> <item>Laag</item>
</string-array> </string-array>
<string name="unfollow_confirm">Wilt u dit account ontvouwen?</string> <string name="unfollow_confirm">Wilt u dit account ontvolgen?</string>
<string name="title_video_peertube">Titel voor de video</string> <string name="title_video_peertube">Titel voor de video</string>
<string name="join_peertube">Word lid van Peertube</string> <string name="join_peertube">Word lid van Peertube</string>
<string name="agreement_check_peertube">Ik ben minstens 16 jaar oud en ga akkoord met de %1$s van dit geval</string> <string name="agreement_check_peertube">Ik ben minstens 16 jaar oud en ga akkoord met de %1$s van dit geval</string>
<string name="edit_profile">Profiel bewerken</string> <string name="edit_profile">Profiel bewerken</string>
<string name="make_an_action">Maak een actie</string> <string name="make_an_action">Maak een actie</string>
<string name="action_unfollow">Ontvouw</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Gevoelige video\'s weergeven</string> <string name="display_nsfw_videos">Gevoelige video\'s weergeven</string>
<string name="fullscreen">Volledig scherm</string> <string name="fullscreen">Volledig scherm</string>
<string name="bookmark_peertube_empty">Er zijn geen video\'s in uw favorieten!</string> <string name="bookmark_peertube_empty">Er zijn geen video\'s in uw favorieten!</string>
<string name="delete_channel">Verwijder kanaal</string> <string name="delete_channel">Verwijder kanaal</string>
<string name="action_channel_confirm_delete">Weet u zeker dat u dit kanaal permanent zult verwijderen?</string> <string name="action_channel_confirm_delete">Weet u zeker dat u dit kanaal permanent zult verwijderen?</string>
<string name="modify_playlists">Video in afspeellijsten</string> <string name="modify_playlists">Video in afspeellijsten</string>
<string name="no_muted">Geen gedempte rekeningen!</string> <string name="no_muted">Geen gedempte accounts!</string>
<string name="error_display_name_channel">U moet een naam en een weergavenaam voor dit kanaal definiëren!</string> <string name="error_display_name_channel">U moet een naam en een weergavenaam voor dit kanaal definiëren!</string>
<string name="action_channel_create">Creëer een kanaal</string> <string name="action_channel_create">Creëer een kanaal</string>
<string name="action_channel_edit">Edit kanaal</string> <string name="action_channel_edit">Edit kanaal</string>
<string name="email_error_domain">E-mailadressen in %1$s zijn niet toegestaan!</string> <string name="email_error_domain">E-mailadressen in %1$s zijn niet toegestaan!</string>
<string name="report_comment_size">Geef de redenen op</string> <string name="report_comment_size">Geef de redenen op</string>
<string name="not_logged_in">U moet worden geauthenticeerd om tot deze actie over te gaan!</string> <string name="not_logged_in">U moet worden geauthenticeerd om tot deze actie over te gaan!</string>
<string name="successful_report">De rekening is gemeld!</string> <string name="successful_report">Het account is gerapporteerd!</string>
<string name="successful_report_comment">Het commentaar is gemeld!</string> <string name="successful_report_comment">Het commentaar is gemeld!</string>
<string name="successful_video_report">De video is gemeld!</string> <string name="successful_video_report">De video is gemeld!</string>
<string name="password_length_error">Het wachtwoord moet minimaal 6 karakters bevatten!</string> <string name="password_length_error">Het wachtwoord moet minimaal 6 karakters bevatten!</string>
<string name="muted_done">De rekening is gedempt!</string> <string name="muted_done">Het account is gedempt!</string>
<string name="edit_video">Bewerk video</string> <string name="edit_video">Bewerk video</string>
<string name="create_an_account">Creëer een account</string> <string name="create_an_account">Creëer een account</string>
<string name="followers_count">%1$s Abonnees</string> <string name="followers_count">%1$s Abonnees</string>
@ -263,8 +329,9 @@
<string name="pickup_categories">Kies categorieën</string> <string name="pickup_categories">Kies categorieën</string>
<string name="pickup_languages">Kies talen</string> <string name="pickup_languages">Kies talen</string>
<string name="notification_channel_name">Informatie actualiseren</string> <string name="notification_channel_name">Informatie actualiseren</string>
<string name="fetch_notification_channel_name">Notificaties ophalen</string>
<string name="add_account">Een account toevoegen</string> <string name="add_account">Een account toevoegen</string>
<string name="list_of_accounts">Lijst van rekeningen</string> <string name="list_of_accounts">Lijst van accounts</string>
<string name="pause">Pauze</string> <string name="pause">Pauze</string>
<string name="play">Speel</string> <string name="play">Speel</string>
<string name="minimize">Minimaliseer</string> <string name="minimize">Minimaliseer</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_autoplay">Automatic playback</string> <string name="set_video_in_list">Filmy na liście</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_video_in_list_description">Zmień układ wyświetlania filmów na liście</string>
<string name="set_fullscreen">Fullscreen</string> <string name="no_instances">Brak instancji!</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="show_more">Pokaż więcej</string>
<string name="show_less">Pokaż mniej</string>
<string name="set_play_screen_lock">Blokada ekranu</string>
<string name="set_play_screen_lock_description">Odtwarzaj filmy kiedy ekran jest zablokowany</string>
<string name="save">Zapisz</string>
<string name="enable_history">Włącz historię</string>
<string name="change_profile_picture">Zmień zdjęcie profilowe</string>
<string name="set_autoplay">Automatyczne odtwarzanie</string>
<string name="set_autoplay_description">Jeśli włączone, filmy będą odtwarzane automatycznie</string>
<string name="set_fullscreen">Pełny ekran</string>
<string name="set_fullscreen_description">Automatycznie otwieraj filmy w trybie pełnoekranowym</string>
<string name="set_autoplay_next_video_settings">Autoodtwarzanie</string>
<string name="set_autoplay_next_video">Automatycznie rozpocznij odtwarzanie następnego filmu</string>
<string name="set_autoplay_next_video_description">Kiedy film się skończy, odtwórz następny sugerowany film.</string>
<string name="add_public_reply">Dodaj publiczną odpowiedź</string> <string name="add_public_reply">Dodaj publiczną odpowiedź</string>
<string name="originally_published">Oryginalnie opublikowane</string>
<string name="activity">Aktywność</string>
<string name="app">Aplikacja</string>
<string name="notif_new_video">Nowy film z twoich subskrypcji</string>
<string name="notif_new_comment">Nowy komentarz do Twojego filmu</string>
<string name="notif_blocked">Jeden z Twoich filmów jest zablokowany/odblokowany</string>
<string name="notif_video_published">Wideo opublikowane (po transkodowaniu/zaplanowanej aktualizacji)</string>
<string name="notif_video_imported">Import wideo zakończony</string>
<string name="notif_new_followers">Ty lub Twój kanał ma nowego obserwującego</string>
<string name="notif_video_mention">Ktoś wspomniał o tobie w komentarzach</string>
<string name="notif_abuse_received">Raport o nadużyciach otrzymał nową wiadomość</string>
<string name="notif_abuse_accepted">Jeden z Twoich raportów o nadużyciach został zaakceptowany lub odrzucony przez moderatorów</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d odpowiedź</item> <item quantity="one">%d odpowiedź</item>
<item quantity="few">%d odpowiedzi</item> <item quantity="few">%d odpowiedzi</item>
@ -14,7 +39,7 @@
<string name="reply">Odpowiedz</string> <string name="reply">Odpowiedz</string>
<string name="set_theme">Motyw</string> <string name="set_theme">Motyw</string>
<string name="set_theme_description">Zezwól na zmianę motywu aplikacji</string> <string name="set_theme_description">Zezwól na zmianę motywu aplikacji</string>
<string name="federation_issue">The video cannot be federated!</string> <string name="federation_issue">Film nie może być zfederowany!</string>
<string name="title_home">Początek</string> <string name="title_home">Początek</string>
<string name="title_local">Lokalne</string> <string name="title_local">Lokalne</string>
<string name="title_discover">Odkrywaj</string> <string name="title_discover">Odkrywaj</string>
@ -40,9 +65,28 @@
<string name="upload_video">Prześlij</string> <string name="upload_video">Prześlij</string>
<string name="image_preview">Podgląd obrazu</string> <string name="image_preview">Podgląd obrazu</string>
<string name="file_to_upload">Wybierz plik do przesłania</string> <string name="file_to_upload">Wybierz plik do przesłania</string>
<string name="new_video">Nowy film</string>
<string name="new_blacklist">Nowe informacje o czarnej liście</string>
<string name="new_my_video_published">Twój film został opublikowany</string>
<string name="new_my_video_error">Błąd podczas publikowania filmu</string>
<string name="new_comment">Nowy komentarz</string>
<string name="new_follow">Nowy obserwujący</string>
<string name="channel">Kanał</string> <string name="channel">Kanał</string>
<string name="videos">Filmy</string> <string name="videos">Filmy</string>
<string name="channels">Kanały</string> <string name="channels">Kanały</string>
<string name="refresh_every">Sprawdzaj co:</string>
<string-array name="refresh_time">
<item>Nigdy</item>
<item>15 minut</item>
<item>30 minut</item>
<item>1 godzina</item>
<item>2 godziny</item>
<item>6 godzin</item>
<item>12 godzin</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Tak</string> <string name="yes">Tak</string>
<string name="no">Nie</string> <string name="no">Nie</string>
<string name="cancel">Anuluj</string> <string name="cancel">Anuluj</string>
@ -62,6 +106,7 @@
<string name="video_uploaded_action">Dotknij tutaj, aby edytować dane filmu.</string> <string name="video_uploaded_action">Dotknij tutaj, aby edytować dane filmu.</string>
<string name="toot_select_image_error">Podczas wyboru nośnika wystąpił błąd!</string> <string name="toot_select_image_error">Podczas wyboru nośnika wystąpił błąd!</string>
<string name="download_file">Pobierz %1$s</string> <string name="download_file">Pobierz %1$s</string>
<string name="account_updated">Konto zostało zaktualizowane!</string>
<string name="action_privacy">Prywatność</string> <string name="action_privacy">Prywatność</string>
<string name="action_logout">Wyloguj</string> <string name="action_logout">Wyloguj</string>
<string name="login">Zaloguj</string> <string name="login">Zaloguj</string>
@ -80,8 +125,15 @@
<string name="toast_error_loading_account">Wystąpił błąd podczas przełączania konta!</string> <string name="toast_error_loading_account">Wystąpił błąd podczas przełączania konta!</string>
<string name="toast_error_search">Podczas wyszukiwania wystąpił błąd!</string> <string name="toast_error_search">Podczas wyszukiwania wystąpił błąd!</string>
<string name="nothing_to_do">Nie można podjąć żadnych działań</string> <string name="nothing_to_do">Nie można podjąć żadnych działań</string>
<string name="action_follow">Obserwuj</string> <string name="action_follow">Subskrybuj</string>
<string name="action_mute">Wycisz</string> <string name="action_mute">Wycisz</string>
<string name="unlimited">Bez ograniczeń</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Całkowity limit filmów</string>
<string name="daily_video_quota">Dzienny limit filmów</string>
<string name="nsfw_title_warning">Dojrzała lub jawna zawartość</string>
<string name="nsfw_message_warning">Ten film zawiera treści dojrzałe lub jawne. Czy na pewno chcesz go obejrzeć?</string>
<string name="search">Szukaj</string> <string name="search">Szukaj</string>
<string name="delete">Usuń</string> <string name="delete">Usuń</string>
<string name="action_lists_confirm_delete">Czy na pewno chcesz na stałe usunąć tę listę?</string> <string name="action_lists_confirm_delete">Czy na pewno chcesz na stałe usunąć tę listę?</string>
@ -95,6 +147,8 @@
<string name="app_logo">Logo aplikacji</string> <string name="app_logo">Logo aplikacji</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Abonamenty</string> <string name="subscriptions">Abonamenty</string>
<string name="delete_instance">Usuń instancję</string>
<string name="delete_instance_confirm">Czy na pewno chcesz usunąć tę instancję?</string>
<string name="delete_comment">Usuń komentarz</string> <string name="delete_comment">Usuń komentarz</string>
<string name="delete_comment_confirm">Czy na pewno usuniesz ten komentarz?</string> <string name="delete_comment_confirm">Czy na pewno usuniesz ten komentarz?</string>
<string name="set_video_mode">Tryb dla filmów wideo</string> <string name="set_video_mode">Tryb dla filmów wideo</string>
@ -109,7 +163,7 @@
<string name="last_365_days">Ostatnie 365 dni</string> <string name="last_365_days">Ostatnie 365 dni</string>
<string name="sepia_element_duration">Czas trwania</string> <string name="sepia_element_duration">Czas trwania</string>
<string name="duration_short"><![CDATA[Krótkie (<4 min)]]></string> <string name="duration_short"><![CDATA[Krótkie (<4 min)]]></string>
<string name="duration_medium"><![CDATA[Medium (410 min)]]></string> <string name="duration_medium"><![CDATA[Średnia (410 min)]]></string>
<string name="duration_long"><![CDATA[Długie (> 10 min)]]></string> <string name="duration_long"><![CDATA[Długie (> 10 min)]]></string>
<string name="display_all_categories">Wyświetl wszystkie kategorie</string> <string name="display_all_categories">Wyświetl wszystkie kategorie</string>
<string name="display_all_licenses">Wyświetl wszystkie licencje</string> <string name="display_all_licenses">Wyświetl wszystkie licencje</string>
@ -124,7 +178,7 @@
</string-array> </string-array>
<string name="sort_by">Sortuj według</string> <string name="sort_by">Sortuj według</string>
<string name="sepia_search_hint">Słowo kluczowe, kanał, film itp.</string> <string name="sepia_search_hint">Słowo kluczowe, kanał, film itp.</string>
<string name="sepia_indication">Sepia Search displays videos and channels that match your search but is not the publisher, nor the owner. If you notice any problems with a video, report it to the administrators on the PeerTube website where the video is published.</string> <string name="sepia_indication">Sepia Search wyświetla filmy i kanały pasujące do Twojego wyszukiwania, ale nie jest wydawcą ani właścicielem. Jeśli zauważysz jakiekolwiek problemy z filmem, zgłoś je administratorom na stronie PeerTube, na której film jest publikowany.</string>
<string name="my_videos">Moje filmy</string> <string name="my_videos">Moje filmy</string>
<string name="title">Tytuł</string> <string name="title">Tytuł</string>
<string name="license">Licencja</string> <string name="license">Licencja</string>
@ -173,13 +227,24 @@
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> publikuje nowy film: <b>%2$s</b>]]></string> <string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> publikuje nowy film: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Twój film <b>%1$s</b> został umieszczony na czarnej liście]]></string> <string name="peertube_video_blacklist"><![CDATA[Twój film <b>%1$s</b> został umieszczony na czarnej liście]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Twój film <b>%1$s</b> został usunięty z czarnej listy]]></string> <string name="peertube_video_unblacklist"><![CDATA[Twój film <b>%1$s</b> został usunięty z czarnej listy]]></string>
<string name="peertube_video_report_success"><![CDATA[Your abuse report <b>%1$s</b> has been accepted]]></string> <string name="peertube_video_report_success"><![CDATA[Twój raport o nadużyciach <b>%1$s</b> został zaakceptowany]]></string>
<string name="peertube_video_abuse"><![CDATA[Nowe zgłoszenie nadużycia dla filmu: <b>%1$s</b>]]></string> <string name="peertube_video_abuse"><![CDATA[Nowe zgłoszenie nadużycia dla filmu: <b>%1$s</b>]]></string>
<string name="add_public_comment">Dodaj publiczny komentarz</string> <string name="add_public_comment">Dodaj publiczny komentarz</string>
<string name="send_comment">Prześlij komentarz</string> <string name="send_comment">Prześlij komentarz</string>
<string name="all">Wszystkie</string> <string name="all">Wszystkie</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Szybkość odtwarzania</string>
<string name="normal">Normalny</string>
<string name="delete_history">Wyczyść historię</string>
<string name="delete_history_confirm">Czy na pewno chcesz usunąć całą historię filmów?</string>
<string name="export_list">Eksportuj</string>
<string name="import_list">Importuj</string>
<string name="export_notification_title">Eksport zakończony sukcesem!</string>
<string name="export_notification_content">Dotknij tutaj, aby wysłać eksport przez e-mail</string>
<string name="export_notification_subjet">Nowa playlista</string>
<string name="export_notification_body">Otwórz załączony plik przez TubeLab</string>
<string name="playlists">Listy odtwarzania</string> <string name="playlists">Listy odtwarzania</string>
<string name="no_playlist">Brak playlist</string>
<string name="display_name">Wyświetlana nazwa</string> <string name="display_name">Wyświetlana nazwa</string>
<string name="action_playlist_add">Nie masz żadnej playlisty. Stuknij ikonę \"+\", aby dodać nową listę odtwarzania</string> <string name="action_playlist_add">Nie masz żadnej playlisty. Stuknij ikonę \"+\", aby dodać nową listę odtwarzania</string>
<string name="error_display_name">Musisz podać nazwę wyświetlacza!</string> <string name="error_display_name">Musisz podać nazwę wyświetlacza!</string>
@ -207,9 +272,10 @@
<string name="account">Konto</string> <string name="account">Konto</string>
<string name="report_account">Zgłoś konto</string> <string name="report_account">Zgłoś konto</string>
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normalny</item>
<item>Webview</item> <item>Webview</item>
<item>Webview</item> <item>Magnes</item>
<item>Bezpośrednio</item> <item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Jasny</item> <item>Jasny</item>
@ -227,7 +293,7 @@
<string name="agreement_check_peertube">Mam co najmniej 16 lat i zgadzam się na %1$s w tym przypadku</string> <string name="agreement_check_peertube">Mam co najmniej 16 lat i zgadzam się na %1$s w tym przypadku</string>
<string name="edit_profile">Profil edycyjny</string> <string name="edit_profile">Profil edycyjny</string>
<string name="make_an_action">Podejmij działania</string> <string name="make_an_action">Podejmij działania</string>
<string name="action_unfollow">Rozwiń</string> <string name="action_unfollow">Anuluj subskrypcję</string>
<string name="display_nsfw_videos">Wyświetlanie wrażliwych filmów wideo</string> <string name="display_nsfw_videos">Wyświetlanie wrażliwych filmów wideo</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">Nie ma żadnych filmów w twoich ulubionych!</string> <string name="bookmark_peertube_empty">Nie ma żadnych filmów w twoich ulubionych!</string>
@ -265,6 +331,7 @@
<string name="pickup_categories">Kategorie wyboru</string> <string name="pickup_categories">Kategorie wyboru</string>
<string name="pickup_languages">Wybieranie języków</string> <string name="pickup_languages">Wybieranie języków</string>
<string name="notification_channel_name">Aktualizacja informacji</string> <string name="notification_channel_name">Aktualizacja informacji</string>
<string name="fetch_notification_channel_name">Sprawdź powiadomienia</string>
<string name="add_account">Dodaj konto</string> <string name="add_account">Dodaj konto</string>
<string name="list_of_accounts">Lista rachunków</string> <string name="list_of_accounts">Lista rachunków</string>
<string name="pause">Przerwa</string> <string name="pause">Przerwa</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d resposta</item> <item quantity="one">%d resposta</item>
<item quantity="other">%d respostas</item> <item quantity="other">%d respostas</item>
@ -38,9 +63,28 @@
<string name="upload_video">Enviar</string> <string name="upload_video">Enviar</string>
<string name="image_preview">Image preview</string> <string name="image_preview">Image preview</string>
<string name="file_to_upload">Selecione o ficheiro a enviar</string> <string name="file_to_upload">Selecione o ficheiro a enviar</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">Canal</string> <string name="channel">Canal</string>
<string name="videos">Vídeos</string> <string name="videos">Vídeos</string>
<string name="channels">Canais</string> <string name="channels">Canais</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Sim</string> <string name="yes">Sim</string>
<string name="no">Não</string> <string name="no">Não</string>
<string name="cancel">Cancelar</string> <string name="cancel">Cancelar</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Tap here to edit the video data.</string> <string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">Ocorreu um erro ao selecionar a mídia!</string> <string name="toot_select_image_error">Ocorreu um erro ao selecionar a mídia!</string>
<string name="download_file">Baixar %1$s</string> <string name="download_file">Baixar %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">Privacidade</string> <string name="action_privacy">Privacidade</string>
<string name="action_logout">Sair</string> <string name="action_logout">Sair</string>
<string name="login">Entrar</string> <string name="login">Entrar</string>
@ -78,8 +123,15 @@
<string name="toast_error_loading_account">Ocorreu um erro ao alternar entre as contas!</string> <string name="toast_error_loading_account">Ocorreu um erro ao alternar entre as contas!</string>
<string name="toast_error_search">Ocorreu um erro na pesquisa!</string> <string name="toast_error_search">Ocorreu um erro na pesquisa!</string>
<string name="nothing_to_do">A ação não pode ser feita ou não é suportada</string> <string name="nothing_to_do">A ação não pode ser feita ou não é suportada</string>
<string name="action_follow">Seguir</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Silenciar</string> <string name="action_mute">Silenciar</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Pesquisa</string> <string name="search">Pesquisa</string>
<string name="delete">Remover</string> <string name="delete">Remover</string>
<string name="action_lists_confirm_delete">Tem certeza de que deseja excluir permanentemente esta lista?</string> <string name="action_lists_confirm_delete">Tem certeza de que deseja excluir permanentemente esta lista?</string>
@ -93,6 +145,8 @@
<string name="app_logo">Logótipo do aplicativo</string> <string name="app_logo">Logótipo do aplicativo</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Inscrições</string> <string name="subscriptions">Inscrições</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Excluir comentário</string> <string name="delete_comment">Excluir comentário</string>
<string name="delete_comment_confirm">Tem certeza de que deseja excluir este comentário?</string> <string name="delete_comment_confirm">Tem certeza de que deseja excluir este comentário?</string>
<string name="set_video_mode">Modo para vídeos</string> <string name="set_video_mode">Modo para vídeos</string>
@ -177,7 +231,18 @@
<string name="send_comment">Enviar comentário</string> <string name="send_comment">Enviar comentário</string>
<string name="all">Tudo</string> <string name="all">Tudo</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Listas de reprodução</string> <string name="playlists">Listas de reprodução</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Nome de exibição</string> <string name="display_name">Nome de exibição</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">Você deve inserir um nome de exibição!</string> <string name="error_display_name">Você deve inserir um nome de exibição!</string>
@ -207,7 +272,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normal</item> <item>Normal</item>
<item>Webview</item> <item>Webview</item>
<item>Transmissão direta</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Diurno</item> <item>Diurno</item>
@ -225,7 +291,7 @@
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string> <string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Editar perfil</string> <string name="edit_profile">Editar perfil</string>
<string name="make_an_action">Make an action</string> <string name="make_an_action">Make an action</string>
<string name="action_unfollow">Deixar de seguir</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -263,6 +329,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Adicionar conta</string> <string name="add_account">Adicionar conta</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d răspuns</item> <item quantity="one">%d răspuns</item>
<item quantity="few">%d răspunsuri</item> <item quantity="few">%d răspunsuri</item>
@ -39,9 +64,28 @@
<string name="upload_video">Upload</string> <string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string> <string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string> <string name="file_to_upload">Select the file to upload</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">Channel</string> <string name="channel">Channel</string>
<string name="videos">Videos</string> <string name="videos">Videos</string>
<string name="channels">Channels</string> <string name="channels">Channels</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Da</string> <string name="yes">Da</string>
<string name="no">Nu</string> <string name="no">Nu</string>
<string name="cancel">Anulare</string> <string name="cancel">Anulare</string>
@ -61,6 +105,7 @@
<string name="video_uploaded_action">Tap here to edit the video data.</string> <string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">A aparut o eroare în timp ce selectați media!</string> <string name="toot_select_image_error">A aparut o eroare în timp ce selectați media!</string>
<string name="download_file">Descărcat %1$s</string> <string name="download_file">Descărcat %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">Confidențialitate</string> <string name="action_privacy">Confidențialitate</string>
<string name="action_logout">Deconectare</string> <string name="action_logout">Deconectare</string>
<string name="login">Autentificare</string> <string name="login">Autentificare</string>
@ -79,8 +124,15 @@
<string name="toast_error_loading_account">A apărut o eroare în timp ce schimbați între conturi!</string> <string name="toast_error_loading_account">A apărut o eroare în timp ce schimbați între conturi!</string>
<string name="toast_error_search">S-a produs o eroare în timpul căutării!</string> <string name="toast_error_search">S-a produs o eroare în timpul căutării!</string>
<string name="nothing_to_do">Nu se poate efectua nici o acțiune</string> <string name="nothing_to_do">Nu se poate efectua nici o acțiune</string>
<string name="action_follow">Urmărește</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Mod silențios</string> <string name="action_mute">Mod silențios</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Căutare</string> <string name="search">Căutare</string>
<string name="delete">Șterge</string> <string name="delete">Șterge</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string> <string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
@ -94,6 +146,8 @@
<string name="app_logo">Logo of the application</string> <string name="app_logo">Logo of the application</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Subscriptions</string> <string name="subscriptions">Subscriptions</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Delete a comment</string> <string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string> <string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string> <string name="set_video_mode">Mode for videos</string>
@ -178,7 +232,18 @@
<string name="send_comment">Send comment</string> <string name="send_comment">Send comment</string>
<string name="all">All</string> <string name="all">All</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Playlists</string> <string name="playlists">Playlists</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Display name</string> <string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string> <string name="error_display_name">You must provide a display name!</string>
@ -208,7 +273,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normal</item> <item>Normal</item>
<item>Webview</item> <item>Webview</item>
<item>Direct stream</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Light</item> <item>Light</item>
@ -226,7 +292,7 @@
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string> <string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Editează profilul</string> <string name="edit_profile">Editează profilul</string>
<string name="make_an_action">Make an action</string> <string name="make_an_action">Make an action</string>
<string name="action_unfollow">Nu mai urmări</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -264,6 +330,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Adaugă un cont</string> <string name="add_account">Adaugă un cont</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_autoplay">Automatic playback</string> <string name="set_video_in_list">Видео в списке</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_video_in_list_description">Изменить расположение для отображения видео в списке</string>
<string name="set_fullscreen">Fullscreen</string> <string name="no_instances">No instances !</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="show_more">Показать еще</string>
<string name="show_less">Показать меньше</string>
<string name="set_play_screen_lock">Блокировка экрана</string>
<string name="set_play_screen_lock_description">Продолжать воспроизведение видео, когда экран заблокирован</string>
<string name="save">Сохранить</string>
<string name="enable_history">Включить историю</string>
<string name="change_profile_picture">Изменить изображение профиля</string>
<string name="set_autoplay">Автоматическое воспроизведение</string>
<string name="set_autoplay_description">Если включено, видео будут воспроизводиться автоматически</string>
<string name="set_fullscreen">Полноэкранный режим</string>
<string name="set_fullscreen_description">Автоматически открывать видео в полноэкранном режиме</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Автоматически начать воспроизведение следующего видео</string>
<string name="set_autoplay_next_video_description">Когда видео заканчивается, перейдите к следующему предложенному видео.</string>
<string name="add_public_reply">Добавить публичный ответ</string> <string name="add_public_reply">Добавить публичный ответ</string>
<string name="originally_published">Originally published</string>
<string name="activity">Действия</string>
<string name="app">Приложение</string>
<string name="notif_new_video">Новое видео из ваших подписок</string>
<string name="notif_new_comment">Новый комментарий к вашему видео</string>
<string name="notif_blocked">Одно из ваших видео заблокировано/разблокировано</string>
<string name="notif_video_published">Видео опубликовано (после перекодирования/запланированного обновления)</string>
<string name="notif_video_imported">Импорт видео завершен</string>
<string name="notif_new_followers">Вы или ваш канал(ы) имеет нового подписчика</string>
<string name="notif_video_mention">Кто-то упомянул вас в видео комментариях</string>
<string name="notif_abuse_received">Отчет о злоупотреблениях получил новое сообщение</string>
<string name="notif_abuse_accepted">Одно из ваших сообщений о злоупотреблениях было принято или отклонено модераторами</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d ответ</item> <item quantity="one">%d ответ</item>
<item quantity="few">%d ответов</item> <item quantity="few">%d ответов</item>
@ -40,9 +65,28 @@
<string name="upload_video">Загрузить</string> <string name="upload_video">Загрузить</string>
<string name="image_preview">Предпросмотр изображения</string> <string name="image_preview">Предпросмотр изображения</string>
<string name="file_to_upload">Выберите файл для загрузки</string> <string name="file_to_upload">Выберите файл для загрузки</string>
<string name="new_video">Новое видео</string>
<string name="new_blacklist">Информация о новом черном списке</string>
<string name="new_my_video_published">Ваше видео опубликовано</string>
<string name="new_my_video_error">Ошибка при публикации вашего видео</string>
<string name="new_comment">Новый комментарий</string>
<string name="new_follow">Новая подписка</string>
<string name="channel">Канал</string> <string name="channel">Канал</string>
<string name="videos">Видео</string> <string name="videos">Видео</string>
<string name="channels">Каналы</string> <string name="channels">Каналы</string>
<string name="refresh_every">Получить каждые:</string>
<string-array name="refresh_time">
<item>Никогда</item>
<item>15 минут</item>
<item>30 минут</item>
<item>1 час</item>
<item>2 часа</item>
<item>6 часов</item>
<item>12 часов</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Да</string> <string name="yes">Да</string>
<string name="no">Нет</string> <string name="no">Нет</string>
<string name="cancel">Отмена</string> <string name="cancel">Отмена</string>
@ -62,6 +106,7 @@
<string name="video_uploaded_action">Нажмите здесь, чтобы редактировать данные видео.</string> <string name="video_uploaded_action">Нажмите здесь, чтобы редактировать данные видео.</string>
<string name="toot_select_image_error">При выборе медиафайла произошла ошибка!</string> <string name="toot_select_image_error">При выборе медиафайла произошла ошибка!</string>
<string name="download_file">Скачать %1$s</string> <string name="download_file">Скачать %1$s</string>
<string name="account_updated">Аккаунт обновлен!</string>
<string name="action_privacy">Конфиденциальность</string> <string name="action_privacy">Конфиденциальность</string>
<string name="action_logout">Выход</string> <string name="action_logout">Выход</string>
<string name="login">Войти</string> <string name="login">Войти</string>
@ -80,8 +125,15 @@
<string name="toast_error_loading_account">Произошла ошибка при переключении между аккаунтами!</string> <string name="toast_error_loading_account">Произошла ошибка при переключении между аккаунтами!</string>
<string name="toast_error_search">Произошла ошибка при поиске!</string> <string name="toast_error_search">Произошла ошибка при поиске!</string>
<string name="nothing_to_do">Ничего нельзя сделать</string> <string name="nothing_to_do">Ничего нельзя сделать</string>
<string name="action_follow">Подписаться</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Игнорировать</string> <string name="action_mute">Игнорировать</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Поиск</string> <string name="search">Поиск</string>
<string name="delete">Удалить</string> <string name="delete">Удалить</string>
<string name="action_lists_confirm_delete">Вы действительно хотите удалить этот список навсегда?</string> <string name="action_lists_confirm_delete">Вы действительно хотите удалить этот список навсегда?</string>
@ -95,6 +147,8 @@
<string name="app_logo">Логотип приложения</string> <string name="app_logo">Логотип приложения</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Подписки</string> <string name="subscriptions">Подписки</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Удалить комментарий</string> <string name="delete_comment">Удалить комментарий</string>
<string name="delete_comment_confirm">Вы уверены, что хотите удалить этот комментарий?</string> <string name="delete_comment_confirm">Вы уверены, что хотите удалить этот комментарий?</string>
<string name="set_video_mode">Режим для видео</string> <string name="set_video_mode">Режим для видео</string>
@ -179,7 +233,18 @@
<string name="send_comment">Оставить комментарий</string> <string name="send_comment">Оставить комментарий</string>
<string name="all">Все</string> <string name="all">Все</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Плейлисты</string> <string name="playlists">Плейлисты</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Отображаемое имя</string> <string name="display_name">Отображаемое имя</string>
<string name="action_playlist_add">У вас нет плейлистов. Нажмите на \"+\", чтобы добавить новый</string> <string name="action_playlist_add">У вас нет плейлистов. Нажмите на \"+\", чтобы добавить новый</string>
<string name="error_display_name">Вы должны указать отображаемое имя!</string> <string name="error_display_name">Вы должны указать отображаемое имя!</string>
@ -209,7 +274,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>По умолчанию</item> <item>По умолчанию</item>
<item>Веб-просмотр</item> <item>Веб-просмотр</item>
<item>Прямой поток</item> <item>Magnet-ссылка</item>
<item>Торрент</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Светлая</item> <item>Светлая</item>
@ -227,7 +293,7 @@
<string name="agreement_check_peertube">Мне 16 или более лет и я согласен с %1$s этого экземпляра</string> <string name="agreement_check_peertube">Мне 16 или более лет и я согласен с %1$s этого экземпляра</string>
<string name="edit_profile">Редактировать профиль</string> <string name="edit_profile">Редактировать профиль</string>
<string name="make_an_action">Предпринять действие</string> <string name="make_an_action">Предпринять действие</string>
<string name="action_unfollow">Отписаться</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Показывать неприличные видео</string> <string name="display_nsfw_videos">Показывать неприличные видео</string>
<string name="fullscreen">На полный экран</string> <string name="fullscreen">На полный экран</string>
<string name="bookmark_peertube_empty">В избранном нет видео!</string> <string name="bookmark_peertube_empty">В избранном нет видео!</string>
@ -265,6 +331,7 @@
<string name="pickup_categories">Выбрать категории</string> <string name="pickup_categories">Выбрать категории</string>
<string name="pickup_languages">Выбрать языки</string> <string name="pickup_languages">Выбрать языки</string>
<string name="notification_channel_name">Обновить данные</string> <string name="notification_channel_name">Обновить данные</string>
<string name="fetch_notification_channel_name">Получать уведомления</string>
<string name="add_account">Добавление аккаунта</string> <string name="add_account">Добавление аккаунта</string>
<string name="list_of_accounts">Список аккаунтов</string> <string name="list_of_accounts">Список аккаунтов</string>
<string name="pause">Пауза</string> <string name="pause">Пауза</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d svar</item> <item quantity="one">%d svar</item>
<item quantity="other">%d svar</item> <item quantity="other">%d svar</item>
@ -38,9 +63,28 @@
<string name="upload_video">Ladda upp</string> <string name="upload_video">Ladda upp</string>
<string name="image_preview">Förhandsvisning</string> <string name="image_preview">Förhandsvisning</string>
<string name="file_to_upload">Välj en fil som ska laddas upp</string> <string name="file_to_upload">Välj en fil som ska laddas upp</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">Kanal</string> <string name="channel">Kanal</string>
<string name="videos">Videor</string> <string name="videos">Videor</string>
<string name="channels">Kanal</string> <string name="channels">Kanal</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Ja</string> <string name="yes">Ja</string>
<string name="no">Nej</string> <string name="no">Nej</string>
<string name="cancel">Avbryt</string> <string name="cancel">Avbryt</string>
@ -60,6 +104,7 @@
<string name="video_uploaded_action">Tap here to edit the video data.</string> <string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">Ett fel uppstod när du valde media!</string> <string name="toot_select_image_error">Ett fel uppstod när du valde media!</string>
<string name="download_file">Laddat ner %1$s</string> <string name="download_file">Laddat ner %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">Sekretess</string> <string name="action_privacy">Sekretess</string>
<string name="action_logout">Logga ut</string> <string name="action_logout">Logga ut</string>
<string name="login">Logga in</string> <string name="login">Logga in</string>
@ -78,8 +123,15 @@
<string name="toast_error_loading_account">Ett fel uppstod vid växling mellan konton!</string> <string name="toast_error_loading_account">Ett fel uppstod vid växling mellan konton!</string>
<string name="toast_error_search">Ett fel uppstod under sökningen!</string> <string name="toast_error_search">Ett fel uppstod under sökningen!</string>
<string name="nothing_to_do">Inga åtgärder kan vidtas</string> <string name="nothing_to_do">Inga åtgärder kan vidtas</string>
<string name="action_follow">Följ</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Tysta</string> <string name="action_mute">Tysta</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Sök</string> <string name="search">Sök</string>
<string name="delete">Ta bort</string> <string name="delete">Ta bort</string>
<string name="action_lists_confirm_delete">Är du säker du vill ta bort listan permanent?</string> <string name="action_lists_confirm_delete">Är du säker du vill ta bort listan permanent?</string>
@ -93,6 +145,8 @@
<string name="app_logo">Applikationens logo</string> <string name="app_logo">Applikationens logo</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Prenumerationer</string> <string name="subscriptions">Prenumerationer</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Ta bort kommentar</string> <string name="delete_comment">Ta bort kommentar</string>
<string name="delete_comment_confirm">Är du säker på att ta bort denna kommentar?</string> <string name="delete_comment_confirm">Är du säker på att ta bort denna kommentar?</string>
<string name="set_video_mode">Lägen för video</string> <string name="set_video_mode">Lägen för video</string>
@ -177,7 +231,18 @@
<string name="send_comment">Skicka kommentar</string> <string name="send_comment">Skicka kommentar</string>
<string name="all">Allt</string> <string name="all">Allt</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Spellistor</string> <string name="playlists">Spellistor</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Visningsnamn</string> <string name="display_name">Visningsnamn</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">Du måste ange ett visningsnamn!</string> <string name="error_display_name">Du måste ange ett visningsnamn!</string>
@ -207,7 +272,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Nomal</item> <item>Nomal</item>
<item>Webbvy</item> <item>Webbvy</item>
<item>Direktström</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>Ljust</item> <item>Ljust</item>
@ -225,7 +291,7 @@
<string name="agreement_check_peertube">Jag är minst 16 år gammal och godkänner %1$s för denna instans</string> <string name="agreement_check_peertube">Jag är minst 16 år gammal och godkänner %1$s för denna instans</string>
<string name="edit_profile">Ändra profil</string> <string name="edit_profile">Ändra profil</string>
<string name="make_an_action">Gör en handling</string> <string name="make_an_action">Gör en handling</string>
<string name="action_unfollow">Sluta följa</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -263,6 +329,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Lägg till ett konto</string> <string name="add_account">Lägg till ett konto</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="title_home">Home</string>
<string name="title_discover">Discover</string>
<string name="title_notifications">Notifications</string>
<string name="title_recently_added">Recently added</string>
<string name="title_trending">Trending</string>
<string name="title_most_liked">Most liked</string>
<string name="toast_error">Oops! An error occurred!</string>
<string name="title_muted">Muted</string>
<string name="title_channel">Channels</string>
<string name="do_not_list">Do not list</string>
<string name="blur">Blur</string>
<string name="display">Display</string>
<string name="no_opinion">No opinion</string>
<string name="instance_choice">Pickup an instance</string>
<string name="not_valide_instance">This instance does not seem to be valid!</string>
<string name="no_videos">No videos!</string>
<string name="favicon">Favicon</string>
<string name="open_with">Open with</string>
<string name="action_playlist_edit">Edit a playlist</string>
<string name="close">Close</string>
<string name="upload_video">Upload</string>
<string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string>
<string name="channel">Channel</string>
<string name="videos">Videos</string>
<string name="channels">Channels</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="cancel">Cancel</string>
<string name="download">Download</string>
<string name="profile_picture">Profile picture</string>
<string name="update_video">Update video</string>
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d m</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d d</string>
<string name="number_view_video">%s views</string>
<string name="title_instance_login">Instance host</string>
<string name="uploading">Uploading, please wait…</string>
<string name="upload_video_success">The video has been uploaded!</string>
<string name="toast_cancelled">Upload cancelled!</string>
<string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">An error occurred while selecting the media!</string>
<string name="download_file">Download %1$s</string>
<string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="email">Email</string>
<string name="tags">Tags</string>
<string name="validate">Validate</string>
<string name="share_with">Share with</string>
<string name="shared_via">Shared via TubeLab</string>
<string name="username">User name</string>
<string name="settings">Settings</string>
<string name="logout_account_confirmation">Are you sure you want to logout @%1$s@%2$s?</string>
<string name="following">Following</string>
<string name="followers">Followers</string>
<string name="client_error">Unable to get client id!</string>
<string name="toast_error_loading_account">An error occurred while switching between accounts!</string>
<string name="toast_error_search">An error occurred while searching!</string>
<string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string>
<string name="action_mute">Mute</string>
<string name="search">Search</string>
<string name="delete">Delete</string>
<string name="action_lists_confirm_delete">Are you sure you want to permanently delete this list?</string>
<string name="action_lists_delete">Delete list</string>
<string name="no_comments">Be the first to leave a comment on this video with the top right button!</string>
<string name="comment_no_allowed_peertube">Comments are not enabled on this video!</string>
<string name="pickup_resolution">Pick up a resolution</string>
<string name="bookmark_add_peertube">The video has been added to bookmarks!</string>
<string name="bookmark_remove_peertube">The video has been removed from bookmarks!</string>
<string name="information" tools:ignore="UnusedResources">Information</string>
<string name="app_logo">Logo of the application</string>
<!-- languages not translated -->
<string name="subscriptions">Subscriptions</string>
<string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string>
<string name="my_videos">My videos</string>
<string name="title">Title</string>
<string name="license">License</string>
<string name="category">Category</string>
<string name="language">Language</string>
<string name="peertube_nsfw">This video contains mature or explicit content</string>
<string name="peertube_enable_comments">Enable video comments</string>
<string name="description">Description</string>
<string name="toast_peertube_video_updated">The video has been updated!</string>
<string name="register_account">Register an account</string>
<string name="email_address">Email address</string>
<string name="preview">Preview</string>
<string name="change_preview">Change preview</string>
<string name="name">Name</string>
<string name="display_more">Display more</string>
<string name="no_channels">No channels!</string>
<string name="report_helper">Some explanations about your report…</string>
<string name="report_video">Report video</string>
<string name="report">Report</string>
<string name="change_instance">Pickup another instance</string>
<string name="my_history">History</string>
<string name="edit">Edit</string>
<string name="set_video_mode_description">Allows to change mode for playing videos (default, streaming or via a browser).</string>
<string name="delete_video">Delete video</string>
<string name="delete_video_confirmation">Are you sure to delete this video?</string>
<string name="no_video_to_display">No videos to display!</string>
<string name="share">Share</string>
<string name="peertube_comment_on_video"><![CDATA[<b>%1$s</b> commented your video <b>%2$s</b>]]></string>
<string name="peertube_follow_channel"><![CDATA[<b>%1$s</b> is following your channel <b>%2$s</b>]]></string>
<string name="peertube_follow_account"><![CDATA[<b>%1$s</b> is following your account]]></string>
<string name="peertube_video_published"><![CDATA[Your video <b>%1$s</b> has been published]]></string>
<string name="peertube_video_import_success"><![CDATA[Your video import <b>%1$s</b> succeeded]]></string>
<string name="peertube_video_import_error"><![CDATA[Your video import <b>%1$s</b> failed]]></string>
<string name="peertube_video_from_subscription"><![CDATA[<b>%1$s</b> published a new video: <b>%2$s</b>]]></string>
<string name="peertube_video_blacklist"><![CDATA[Your video <b>%1$s</b> has been blacklisted]]></string>
<string name="peertube_video_unblacklist"><![CDATA[Your video <b>%1$s</b> has been unblacklisted]]></string>
<string name="add_public_comment">Add a public comment</string>
<string name="send_comment">Send comment</string>
<string name="all">All</string>
<!-- end languages -->
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="password_confirm">Confirm password</string>
<string name="agreement_check">I agree to %1$s and %2$s</string>
<string name="server_rules">server rules</string>
<string name="tos">terms of service</string>
<string name="sign_up">Sign up</string>
<string name="all_field_filled">Please, fill all the fields!</string>
<string name="password_error">Passwords don\'t match!</string>
<string name="email_error">The email doesn\'t seem to be valid!</string>
<string name="email_indicator">You will be sent a confirmation e-mail</string>
<string name="password_indicator">Use at least 8 characters</string>
<string name="password_too_short">Password should contain at least 8 characters</string>
<string name="username_error">Username should only contain letters, numbers and underscores</string>
<string name="account_created">Account created!</string>
<string name="account_created_message"> Your account has been created!\n\n
Think to validate your email within the 48 next hours.\n\n
You can now connect your account by writing <b>%1$s</b> in the first field and tap on <b>Connect</b>.\n\n
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
</string>
<string name="account">Account</string>
<string name="report_account">Report account</string>
<string-array name="settings_video_mode">
<item>Normal</item>
<item>Webview</item>
<item>Direct stream</item>
</string-array>
<string name="unfollow_confirm">Do you want to unfollow this account?</string>
<string name="title_video_peertube">Title for the video</string>
<string name="join_peertube">Join Peertube</string>
<string name="agreement_check_peertube">I am at least 16 years old and agree to the %1$s of this instance</string>
<string name="edit_profile">Edit profile</string>
<string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string>
<string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
<string name="delete_channel">Remove channel</string>
<string name="action_channel_confirm_delete">Are you sure to permanently delete this channel?</string>
<string name="no_muted">No muted accounts!</string>
<string name="error_display_name_channel">You must define a name and a display name for this channel!</string>
<string name="action_channel_create">Create a channel</string>
<string name="action_channel_edit">Edit channel</string>
<string name="email_error_domain">Email addresses in %1$s are not allowed!</string>
<string name="report_comment_size">Please, specify the reasons</string>
<string name="not_logged_in">You must be authenticated to proceed to this action!</string>
<string name="successful_report">The account has been reported!</string>
<string name="successful_video_report">The video has been reported!</string>
<string name="password_length_error">The password must contain at least 6 characters!</string>
<string name="muted_done">The account has been muted!</string>
<string name="edit_video">Edit video</string>
<string name="create_an_account">Create an account</string>
<string name="followers_count">%1$s Subscribers</string>
<string name="developer">Developer</string>
<string name="about_vesrion">Release %1$s</string>
<string name="about_the_app">About the app</string>
<string name="Donate">Donate</string>
<string name="source_code">Source code</string>
<string name="issue_tracker">Issue tracker</string>
<string name="action_instance_empty_content">No instances match these criteria</string>
<string name="instances_picker">Instances picker</string>
<string name="pickup_instance">Pickup this instance</string>
<string name="sensitive_video"> Sensitive videos</string>
<string name="sensitive_content">Sensitive content: %1$s</string>
<string name="followers_instance">%1$s followers instances</string>
<string name="help">Help</string>
<string name="pickup_categories">Pickup categories</string>
<string name="pickup_languages">Pickup languages</string>
<string name="notification_channel_name">Update information</string>
<string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string>
</resources>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">添加公开回复</string> <string name="add_public_reply">添加公开回复</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="other">%d 条回复</item> <item quantity="other">%d 条回复</item>
</plurals> </plurals>
@ -37,9 +62,28 @@
<string name="upload_video">上传</string> <string name="upload_video">上传</string>
<string name="image_preview">图像预览</string> <string name="image_preview">图像预览</string>
<string name="file_to_upload">选择要上传的文件</string> <string name="file_to_upload">选择要上传的文件</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">频道</string> <string name="channel">频道</string>
<string name="videos">视频</string> <string name="videos">视频</string>
<string name="channels">频道</string> <string name="channels">频道</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes"></string> <string name="yes"></string>
<string name="no"></string> <string name="no"></string>
<string name="cancel">取消</string> <string name="cancel">取消</string>
@ -59,6 +103,7 @@
<string name="video_uploaded_action">点击此处以编辑视频内容。</string> <string name="video_uploaded_action">点击此处以编辑视频内容。</string>
<string name="toot_select_image_error">选择媒体文件时出现了错误!</string> <string name="toot_select_image_error">选择媒体文件时出现了错误!</string>
<string name="download_file">下载 %1$s</string> <string name="download_file">下载 %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">隐私</string> <string name="action_privacy">隐私</string>
<string name="action_logout">登出</string> <string name="action_logout">登出</string>
<string name="login">登录</string> <string name="login">登录</string>
@ -77,8 +122,15 @@
<string name="toast_error_loading_account">在切换帐户时出现了错误!</string> <string name="toast_error_loading_account">在切换帐户时出现了错误!</string>
<string name="toast_error_search">搜索时出现了错误!</string> <string name="toast_error_search">搜索时出现了错误!</string>
<string name="nothing_to_do">无法进行任何操作</string> <string name="nothing_to_do">无法进行任何操作</string>
<string name="action_follow">订阅</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">静音</string> <string name="action_mute">静音</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">搜索​​​​</string> <string name="search">搜索​​​​</string>
<string name="delete">删除</string> <string name="delete">删除</string>
<string name="action_lists_confirm_delete">您确定要永久删除此列表吗?</string> <string name="action_lists_confirm_delete">您确定要永久删除此列表吗?</string>
@ -92,6 +144,8 @@
<string name="app_logo">应用程序的标志</string> <string name="app_logo">应用程序的标志</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">订阅列表</string> <string name="subscriptions">订阅列表</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">删除评论</string> <string name="delete_comment">删除评论</string>
<string name="delete_comment_confirm">您确定要删除此评论吗?</string> <string name="delete_comment_confirm">您确定要删除此评论吗?</string>
<string name="set_video_mode">视频播放模式</string> <string name="set_video_mode">视频播放模式</string>
@ -176,7 +230,18 @@
<string name="send_comment">发送评论</string> <string name="send_comment">发送评论</string>
<string name="all">全部</string> <string name="all">全部</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">播放列表</string> <string name="playlists">播放列表</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">显示昵称</string> <string name="display_name">显示昵称</string>
<string name="action_playlist_add">您没有任何播放列表,点击 + 号添加一个新的播放列表</string> <string name="action_playlist_add">您没有任何播放列表,点击 + 号添加一个新的播放列表</string>
<string name="error_display_name">您必须指定一个昵称!</string> <string name="error_display_name">您必须指定一个昵称!</string>
@ -205,7 +270,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>标准</item> <item>标准</item>
<item>网页播放器</item> <item>网页播放器</item>
<item>串流</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item>亮色</item> <item>亮色</item>
@ -223,7 +289,7 @@
<string name="agreement_check_peertube">我已至少年满十六岁,并且同意该实例的 %1$s</string> <string name="agreement_check_peertube">我已至少年满十六岁,并且同意该实例的 %1$s</string>
<string name="edit_profile">编辑个人资料</string> <string name="edit_profile">编辑个人资料</string>
<string name="make_an_action">请选择其中一项操作</string> <string name="make_an_action">请选择其中一项操作</string>
<string name="action_unfollow">取消订阅</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">显示敏感视频</string> <string name="display_nsfw_videos">显示敏感视频</string>
<string name="fullscreen">全屏</string> <string name="fullscreen">全屏</string>
<string name="bookmark_peertube_empty">您的收藏列表为空!</string> <string name="bookmark_peertube_empty">您的收藏列表为空!</string>
@ -261,6 +327,7 @@
<string name="pickup_categories">选择类别</string> <string name="pickup_categories">选择类别</string>
<string name="pickup_languages">选择语言</string> <string name="pickup_languages">选择语言</string>
<string name="notification_channel_name">更新信息</string> <string name="notification_channel_name">更新信息</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">添加账号</string> <string name="add_account">添加账号</string>
<string name="list_of_accounts">账号列表</string> <string name="list_of_accounts">账号列表</string>
<string name="pause">暂停</string> <string name="pause">暂停</string>

View File

@ -1,10 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="other">%d 條回覆</item> <item quantity="other">%d 條回覆</item>
</plurals> </plurals>
@ -37,9 +62,28 @@
<string name="upload_video">上傳</string> <string name="upload_video">上傳</string>
<string name="image_preview">圖片預覽</string> <string name="image_preview">圖片預覽</string>
<string name="file_to_upload">選取要上傳的檔案</string> <string name="file_to_upload">選取要上傳的檔案</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">頻道</string> <string name="channel">頻道</string>
<string name="videos">影片</string> <string name="videos">影片</string>
<string name="channels">頻道</string> <string name="channels">頻道</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes"></string> <string name="yes"></string>
<string name="no"></string> <string name="no"></string>
<string name="cancel">取消</string> <string name="cancel">取消</string>
@ -59,6 +103,7 @@
<string name="video_uploaded_action">Tap here to edit the video data.</string> <string name="video_uploaded_action">Tap here to edit the video data.</string>
<string name="toot_select_image_error">選擇媒體時發生錯誤!</string> <string name="toot_select_image_error">選擇媒體時發生錯誤!</string>
<string name="download_file">下載 %1$s</string> <string name="download_file">下載 %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">隱私權</string> <string name="action_privacy">隱私權</string>
<string name="action_logout">登出</string> <string name="action_logout">登出</string>
<string name="login">登入</string> <string name="login">登入</string>
@ -77,8 +122,15 @@
<string name="toast_error_loading_account">在帳號間切換時發生錯誤!</string> <string name="toast_error_loading_account">在帳號間切換時發生錯誤!</string>
<string name="toast_error_search">搜尋時發生錯誤!</string> <string name="toast_error_search">搜尋時發生錯誤!</string>
<string name="nothing_to_do">無法採取行動</string> <string name="nothing_to_do">無法採取行動</string>
<string name="action_follow">關注</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">靜音</string> <string name="action_mute">靜音</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">搜尋</string> <string name="search">搜尋</string>
<string name="delete">刪除</string> <string name="delete">刪除</string>
<string name="action_lists_confirm_delete">您確定您想要永久刪除此列表嗎?</string> <string name="action_lists_confirm_delete">您確定您想要永久刪除此列表嗎?</string>
@ -92,6 +144,8 @@
<string name="app_logo">應用程式圖示</string> <string name="app_logo">應用程式圖示</string>
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">訂閱</string> <string name="subscriptions">訂閱</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">刪除留言</string> <string name="delete_comment">刪除留言</string>
<string name="delete_comment_confirm">您想要刪除此留言嗎?</string> <string name="delete_comment_confirm">您想要刪除此留言嗎?</string>
<string name="set_video_mode">影片模式</string> <string name="set_video_mode">影片模式</string>
@ -176,7 +230,18 @@
<string name="send_comment">傳送留言</string> <string name="send_comment">傳送留言</string>
<string name="all">全部</string> <string name="all">全部</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">播放清單</string> <string name="playlists">播放清單</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">顯示名稱</string> <string name="display_name">顯示名稱</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">您必須提供顯示名稱!</string> <string name="error_display_name">您必須提供顯示名稱!</string>
@ -206,7 +271,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>正常</item> <item>正常</item>
<item>Torrent</item> <item>Torrent</item>
<item>Webview</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
<string-array name="settings_theme"> <string-array name="settings_theme">
<item></item> <item></item>
@ -224,7 +290,7 @@
<string name="agreement_check_peertube">我至少 16 歲並同意此站台的 %1$s</string> <string name="agreement_check_peertube">我至少 16 歲並同意此站台的 %1$s</string>
<string name="edit_profile">編輯個人資料</string> <string name="edit_profile">編輯個人資料</string>
<string name="make_an_action">做動作</string> <string name="make_an_action">做動作</string>
<string name="action_unfollow">取消追蹤</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
<string name="bookmark_peertube_empty">There are no videos in your favourites!</string> <string name="bookmark_peertube_empty">There are no videos in your favourites!</string>
@ -262,6 +328,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">新增帳號</string> <string name="add_account">新增帳號</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>

View File

@ -7,6 +7,7 @@
<color name="tag_color_text">#FAFAFA</color> <color name="tag_color_text">#FAFAFA</color>
<color name="positive_thumbs">#2b90d9</color> <color name="positive_thumbs">#2b90d9</color>
<color name="negative_thumbs">#F44336</color> <color name="negative_thumbs">#F44336</color>
<color name="backgroundDark">#DD000000</color>
<color name="red_1">#F44336</color> <color name="red_1">#F44336</color>
<color name="gray_light">#80808080</color>
</resources> </resources>

View File

@ -1,23 +1,53 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" translatable="false">Tubelab</string> <string name="app_name" translatable="false">Tubelab</string>
<string name="app_id" translatable="false">app.fedilab.tubelab</string>
<string name="set_video_mode_choice" translatable="false">set_video_mode_choice</string> <string name="set_video_mode_choice" translatable="false">set_video_mode_choice</string>
<string name="set_video_minimize_choice" translatable="false">set_video_minimize_choice</string> <string name="set_video_minimize_choice" translatable="false">set_video_minimize_choice</string>
<string name="set_video_language_choice" translatable="false">set_video_language_choice</string> <string name="set_video_language_choice" translatable="false">set_video_language_choice</string>
<string name="set_video_quality_choice" translatable="false">set_video_quality_choice</string> <string name="set_video_quality_choice" translatable="false">set_video_quality_choice</string>
<string name="set_video_cache_choice" translatable="false">set_video_cache_choice</string> <string name="set_video_cache_choice" translatable="false">set_video_cache_choice</string>
<string name="set_autoplay_choice" translatable="false">set_autoplay_choice</string> <string name="set_autoplay_choice" translatable="false">set_autoplay_choice</string>
<string name="set_store_in_history" translatable="false">set_store_in_history</string>
<string name="set_autoplay_next_video_choice" translatable="false">set_autoplay_next_video_choice</string>
<string name="set_theme_choice" translatable="false">set_theme_choice</string> <string name="set_theme_choice" translatable="false">set_theme_choice</string>
<string name="set_fullscreen_choice" translatable="false">set_fullscreen_choice</string> <string name="set_fullscreen_choice" translatable="false">set_fullscreen_choice</string>
<string name="set_play_screen_lock_choice" translatable="false">set_play_screen_lock_choice</string>
<string name="set_video_in_list_choice" translatable="false">set_video_in_list_choice</string>
<string name="set_video_sensitive_choice" translatable="false">set_video_sensitive_choice</string>
<string name="set_video_in_list">Videos in list</string>
<string name="set_video_in_list_description">Change the layout for displaying videos in a list</string>
<string name="no_instances">No instances !</string>
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="set_play_screen_lock">Screen lock</string>
<string name="set_play_screen_lock_description">Keep playing videos when the screen is locked</string>
<string name="save">Save</string>
<string name="enable_history">Enable history</string>
<string name="change_profile_picture">Change profile picture</string>
<string name="set_autoplay">Automatic playback</string> <string name="set_autoplay">Automatic playback</string>
<string name="set_autoplay_description">If enabled, videos will be played automatically</string> <string name="set_autoplay_description">If enabled, videos will be played automatically</string>
<string name="set_fullscreen">Fullscreen</string> <string name="set_fullscreen">Fullscreen</string>
<string name="set_fullscreen_description">Automatically open videos in fullscreen</string> <string name="set_fullscreen_description">Automatically open videos in fullscreen</string>
<string name="set_autoplay_next_video_settings">Autoplay</string>
<string name="set_autoplay_next_video">Automatically start playing the next video</string>
<string name="set_autoplay_next_video_description">When a video ends, follow up with the next suggested video.</string>
<string name="add_public_reply">Add a public reply</string> <string name="add_public_reply">Add a public reply</string>
<string name="originally_published">Originally published</string>
<string name="activity">Activity</string>
<string name="app">App</string>
<string name="notif_new_video">New video from your subscriptions</string>
<string name="notif_new_comment">New comment on your video</string>
<string name="notif_blocked">One of your video is blocked/unblocked</string>
<string name="notif_video_published">Video published (after transcoding/scheduled update)</string>
<string name="notif_video_imported">Video import finished</string>
<string name="notif_new_followers">You or your channel(s) has a new follower</string>
<string name="notif_video_mention">Someone mentioned you in video comments</string>
<string name="notif_abuse_received">An abuse report received a new message</string>
<string name="notif_abuse_accepted">One of your abuse reports has been accepted or rejected by moderators</string>
<plurals name="number_of_replies"> <plurals name="number_of_replies">
<item quantity="one">%d reply</item> <item quantity="one">%d reply</item>
@ -53,10 +83,31 @@
<string name="image_preview">Image preview</string> <string name="image_preview">Image preview</string>
<string name="file_to_upload">Select the file to upload</string> <string name="file_to_upload">Select the file to upload</string>
<string name="new_video">New video</string>
<string name="new_blacklist">New blacklist info</string>
<string name="new_my_video_published">Your video is published</string>
<string name="new_my_video_error">Error when publishing your video</string>
<string name="new_comment">New comment</string>
<string name="new_follow">New follow</string>
<string name="channel">Channel</string> <string name="channel">Channel</string>
<string name="videos">Videos</string> <string name="videos">Videos</string>
<string name="channels">Channels</string> <string name="channels">Channels</string>
<string name="refresh_every">Fetch every:</string>
<string-array name="refresh_time">
<item>Never</item>
<item>15 minutes</item>
<item>30 minutes</item>
<item>1 hour</item>
<item>2 hours</item>
<item>6 hours</item>
<item>12 hours</item>
</string-array>
<string name="_retry">Retry</string>
<string name="refresh_token_failed">Token refresh failed!</string>
<string name="refresh_token_failed_message">You can retry this action or simply disconnect the current account</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
<string name="no">No</string> <string name="no">No</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
@ -81,6 +132,7 @@
<string name="download_file">Download %1$s</string> <string name="download_file">Download %1$s</string>
<string name="account_updated">The account has been updated!</string>
<string name="action_privacy">Privacy</string> <string name="action_privacy">Privacy</string>
<string name="action_logout">Logout</string> <string name="action_logout">Logout</string>
@ -107,10 +159,18 @@
<string name="nothing_to_do">No action can be taken</string> <string name="nothing_to_do">No action can be taken</string>
<string name="action_follow">Follow</string> <string name="action_follow">Subscribe</string>
<string name="action_mute">Mute</string> <string name="action_mute">Mute</string>
<string name="unlimited">Unlimited</string>
<string name="mb">MB</string>
<string name="gb">GB</string>
<string name="total_video_quota">Total video quota</string>
<string name="daily_video_quota">Daily video quota</string>
<string name="nsfw_title_warning">Mature or explicit content</string>
<string name="nsfw_message_warning">This video contains mature or explicit content. Are you sure you want to watch it?</string>
<string name="search">Search</string> <string name="search">Search</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
@ -133,6 +193,9 @@
<!-- languages not translated --> <!-- languages not translated -->
<string name="subscriptions">Subscriptions</string> <string name="subscriptions">Subscriptions</string>
<string name="delete_instance">Delete an instance</string>
<string name="delete_instance_confirm">Are you sure to delete this instance?</string>
<string name="delete_comment">Delete a comment</string> <string name="delete_comment">Delete a comment</string>
<string name="delete_comment_confirm">Are you sure to delete this comment?</string> <string name="delete_comment_confirm">Are you sure to delete this comment?</string>
<string name="set_video_mode">Mode for videos</string> <string name="set_video_mode">Mode for videos</string>
@ -232,8 +295,20 @@
<string name="send_comment">Send comment</string> <string name="send_comment">Send comment</string>
<string name="all">All</string> <string name="all">All</string>
<!-- end languages --> <!-- end languages -->
<string name="playback_speed">Playback speed</string>
<string name="normal">Normal</string>
<string name="delete_history">Delete videos history</string>
<string name="delete_history_confirm">Are you sure you want to delete all your videos history?</string>
<string name="export_list">Export</string>
<string name="import_list">Import</string>
<string name="export_notification_title">Successful export!</string>
<string name="export_notification_content">Tap here to send the export by email</string>
<string name="export_notification_subjet">New Playlist</string>
<string name="export_notification_body">Open the attached file with TubeLab</string>
<string name="playlists">Playlists</string> <string name="playlists">Playlists</string>
<string name="no_playlist">No playlists</string>
<string name="display_name">Display name</string> <string name="display_name">Display name</string>
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string> <string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string> <string name="error_display_name">You must provide a display name!</string>
@ -265,7 +340,8 @@
<string-array name="settings_video_mode"> <string-array name="settings_video_mode">
<item>Normal</item> <item>Normal</item>
<item>Webview</item> <item>Webview</item>
<item>Direct stream</item> <item>Magnet</item>
<item>Torrent</item>
</string-array> </string-array>
@ -292,7 +368,7 @@
<string name="make_an_action">Make an action</string> <string name="make_an_action">Make an action</string>
<string name="action_unfollow">Unfollow</string> <string name="action_unfollow">Unsubscribe</string>
<string name="display_nsfw_videos">Display sensitive videos</string> <string name="display_nsfw_videos">Display sensitive videos</string>
<string name="fullscreen">Fullscreen</string> <string name="fullscreen">Fullscreen</string>
@ -345,6 +421,7 @@
<string name="pickup_categories">Pick categories</string> <string name="pickup_categories">Pick categories</string>
<string name="pickup_languages">Pick languages</string> <string name="pickup_languages">Pick languages</string>
<string name="notification_channel_name">Update information</string> <string name="notification_channel_name">Update information</string>
<string name="fetch_notification_channel_name">Fetch notifications</string>
<string name="add_account">Add an account</string> <string name="add_account">Add an account</string>
<string name="list_of_accounts">List of accounts</string> <string name="list_of_accounts">List of accounts</string>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_images"
path="/TubeLab/" />
</paths>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.fedilab.fedilabtube">
<application
android:name=".FedilabTube"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name=".MainActivity"
tools:node="merge">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.tubelab" />
<data android:pathPattern=".*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.tubelab" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.tubelab" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.fedilab.fedilabtube">
<application
android:name=".FedilabTube"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name=".PeertubeActivity"
tools:node="mergeOnlyAttributes">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- The app is a good candidate for URL in https://domain.name/videos/watch/xxxxx-->
<data
android:host="*"
android:pathPrefix="/videos/watch/"
android:scheme="https" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -18,7 +18,7 @@
<application <application
android:name=".FedilabTube" android:name=".FedilabTube"
android:allowBackup="false" android:allowBackup="false"
android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
@ -68,6 +68,11 @@
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:label="@string/app_name" android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" /> android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".MyAccountActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity <activity
android:name=".SearchActivity" android:name=".SearchActivity"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
@ -78,7 +83,11 @@
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:label="@string/app_name" android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" /> android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".AllLocalPlaylistsActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity <activity
android:name=".InstancePickerActivity" android:name=".InstancePickerActivity"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
@ -90,6 +99,11 @@
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:label="@string/app_name" android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" /> android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".LocalPlaylistsActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity <activity
android:name=".VideosTimelineActivity" android:name=".VideosTimelineActivity"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
@ -100,6 +114,11 @@
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:label="@string/sepia_search" android:label="@string/sepia_search"
android:windowSoftInputMode="stateAlwaysHidden" /> android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".ManageInstancesActivity"
android:configChanges="orientation|screenSize"
android:label="@string/instances_picker"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity <activity
android:name=".WebviewActivity" android:name=".WebviewActivity"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
@ -138,13 +157,23 @@
<service <service
android:name=".services.RetrieveInfoService" android:name=".services.RetrieveInfoService"
android:exported="false" /> android:exported="false" />
<receiver
android:name=".services.PeertubeUploadReceiver" <provider
android:exported="false"> android:name="androidx.work.impl.WorkManagerInitializer"
<intent-filter> android:authorities="${applicationId}.workmanager-init"
<action android:name="app.fedilab.fedilabtube.uploadservice.broadcast.status" /> tools:node="remove"
</intent-filter> android:exported="false" />
</receiver>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application> </application>
</manifest> </manifest>

View File

@ -37,19 +37,18 @@ import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.AccountData.Account; import app.fedilab.fedilabtube.client.data.AccountData.Account;
import app.fedilab.fedilabtube.drawer.OwnAccountsAdapter;
import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment; import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment;
import app.fedilab.fedilabtube.fragment.DisplayChannelsFragment; import app.fedilab.fedilabtube.fragment.DisplayChannelsFragment;
import app.fedilab.fedilabtube.fragment.DisplayNotificationsFragment; import app.fedilab.fedilabtube.fragment.DisplayNotificationsFragment;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.helper.SwitchAccountHelper;
import app.fedilab.fedilabtube.sqlite.AccountDAO; import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.sqlite.Sqlite;
@ -99,6 +98,8 @@ public class AccountActivity extends AppCompatActivity {
displayname.setText(account.getDisplayName()); displayname.setText(account.getDisplayName());
instanceView.setText(account.getHost()); instanceView.setText(account.getHost());
FloatingActionButton edit_profile = findViewById(R.id.edit_profile);
edit_profile.setOnClickListener(v -> startActivity(new Intent(AccountActivity.this, MyAccountActivity.class)));
Button logout_button = findViewById(R.id.logout_button); Button logout_button = findViewById(R.id.logout_button);
logout_button.setOnClickListener(v -> { logout_button.setOnClickListener(v -> {
@ -210,42 +211,7 @@ public class AccountActivity extends AppCompatActivity {
finish(); finish();
return true; return true;
} else if (item.getItemId() == R.id.action_add_account) { } else if (item.getItemId() == R.id.action_add_account) {
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); SwitchAccountHelper.switchDialog(AccountActivity.this, true);
List<Account> accounts = new AccountDAO(AccountActivity.this, db).getAllAccount();
AlertDialog.Builder builderSingle = new AlertDialog.Builder(AccountActivity.this);
builderSingle.setTitle(getString(R.string.list_of_accounts));
if (accounts != null) {
final OwnAccountsAdapter accountsListAdapter = new OwnAccountsAdapter(AccountActivity.this, accounts);
final Account[] accountArray = new Account[accounts.size()];
int i = 0;
for (Account account : accounts) {
accountArray[i] = account;
i++;
}
builderSingle.setAdapter(accountsListAdapter, (dialog, which) -> {
final Account account = accountArray[which];
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, account.getToken());
editor.putString(Helper.PREF_INSTANCE, account.getHost());
editor.putString(Helper.PREF_KEY_ID, account.getId());
editor.putString(Helper.PREF_KEY_NAME, account.getUsername());
editor.apply();
dialog.dismiss();
Intent intent = new Intent(AccountActivity.this, MainActivity.class);
startActivity(intent);
finish();
});
}
builderSingle.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderSingle.setPositiveButton(R.string.add_account, (dialog, which) -> {
Intent intent = new Intent(AccountActivity.this, LoginActivity.class);
startActivity(intent);
finish();
});
builderSingle.show();
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }

View File

@ -0,0 +1,120 @@
package app.fedilab.fedilabtube;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist;
import app.fedilab.fedilabtube.client.data.VideoPlaylistData;
import app.fedilab.fedilabtube.drawer.PlaylistAdapter;
import app.fedilab.fedilabtube.viewmodel.PlaylistsVM;
public class AllLocalPlaylistsActivity extends AppCompatActivity implements PlaylistAdapter.AllPlaylistRemoved {
PlaylistAdapter playlistAdapter;
private RelativeLayout mainLoader;
private RelativeLayout textviewNoAction;
private List<Playlist> playlists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_playlist);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(R.string.playlists);
textviewNoAction = findViewById(R.id.no_action);
mainLoader = findViewById(R.id.loader);
RelativeLayout nextElementLoader = findViewById(R.id.loading_next_items);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
PlaylistsVM viewModel = new ViewModelProvider(AllLocalPlaylistsActivity.this).get(PlaylistsVM.class);
viewModel.localePlaylist().observe(AllLocalPlaylistsActivity.this, this::manageVIewPlaylists);
FloatingActionButton add_new = findViewById(R.id.add_new);
add_new.setVisibility(View.GONE);
TextView no_action_text = findViewById(R.id.no_action_text);
no_action_text.setText(R.string.no_playlist);
playlists = new ArrayList<>();
RecyclerView lv_playlist = findViewById(R.id.lv_playlist);
playlistAdapter = new PlaylistAdapter(playlists, true);
playlistAdapter.allPlaylistRemoved = this;
lv_playlist.setAdapter(playlistAdapter);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(AllLocalPlaylistsActivity.this);
lv_playlist.setLayoutManager(mLayoutManager);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public void manageVIewPlaylists(List<VideoPlaylistData.VideoPlaylistExport> videoPlaylistExports) {
mainLoader.setVisibility(View.GONE);
if (videoPlaylistExports == null) {
textviewNoAction.setVisibility(View.VISIBLE);
return;
}
if (videoPlaylistExports.size() > 0) {
for (VideoPlaylistData.VideoPlaylistExport videoPlaylistExport : videoPlaylistExports) {
playlists.add(videoPlaylistExport.getPlaylist());
}
playlistAdapter.notifyDataSetChanged();
textviewNoAction.setVisibility(View.GONE);
} else {
textviewNoAction.setVisibility(View.VISIBLE);
}
}
@Override
public void onAllPlaylistRemoved() {
textviewNoAction.setVisibility(View.VISIBLE);
}
}

View File

@ -14,7 +14,12 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.Manifest;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -27,18 +32,19 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -53,52 +59,53 @@ import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist; import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist;
import app.fedilab.fedilabtube.client.entities.Item; import app.fedilab.fedilabtube.client.entities.Item;
import app.fedilab.fedilabtube.client.entities.PlaylistParams; import app.fedilab.fedilabtube.client.entities.PlaylistParams;
import app.fedilab.fedilabtube.databinding.ActivityAllPlaylistBinding;
import app.fedilab.fedilabtube.databinding.AddPlaylistBinding;
import app.fedilab.fedilabtube.drawer.PlaylistAdapter; import app.fedilab.fedilabtube.drawer.PlaylistAdapter;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; import app.fedilab.fedilabtube.viewmodel.PlaylistsVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation; import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class AllPlaylistsActivity extends AppCompatActivity { public class AllPlaylistsActivity extends AppCompatActivity implements PlaylistAdapter.AllPlaylistRemoved {
PlaylistAdapter playlistAdapter; PlaylistAdapter playlistAdapter;
private RelativeLayout mainLoader;
private RelativeLayout textviewNoAction;
private HashMap<Integer, String> privacyToSend; private HashMap<Integer, String> privacyToSend;
private Spinner set_upload_channel;
private Spinner set_upload_privacy;
private String idChannel; private String idChannel;
private List<Playlist> playlists; private List<Playlist> playlists;
private Playlist playlistToEdit; private Playlist playlistToEdit;
private List<ChannelData.Channel> myChannels; private List<ChannelData.Channel> myChannels;
private ChannelData.Channel selectedChannel; private ChannelData.Channel selectedChannel;
private static final int PICK_AVATAR = 467;
private AddPlaylistBinding bindingDialog;
private Uri inputData;
private ActivityAllPlaylistBinding binding;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_playlist); binding = ActivityAllPlaylistBinding.inflate(getLayoutInflater());
View viewRoot = binding.getRoot();
setContentView(viewRoot);
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(R.string.playlists); setTitle(R.string.playlists);
textviewNoAction = findViewById(R.id.no_action); binding.loader.setVisibility(View.VISIBLE);
mainLoader = findViewById(R.id.loader); binding.loadingNextItems.setVisibility(View.GONE);
RelativeLayout nextElementLoader = findViewById(R.id.loading_next_items);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
idChannel = null; idChannel = null;
PlaylistsVM viewModel = new ViewModelProvider(AllPlaylistsActivity.this).get(PlaylistsVM.class); PlaylistsVM viewModel = new ViewModelProvider(AllPlaylistsActivity.this).get(PlaylistsVM.class);
viewModel.manage(PlaylistsVM.action.GET_PLAYLISTS, null, null).observe(AllPlaylistsActivity.this, apiResponse -> manageVIewPlaylists(PlaylistsVM.action.GET_PLAYLISTS, apiResponse)); viewModel.manage(PlaylistsVM.action.GET_PLAYLISTS, null, null).observe(AllPlaylistsActivity.this, apiResponse -> manageVIewPlaylists(PlaylistsVM.action.GET_PLAYLISTS, apiResponse));
FloatingActionButton add_new = findViewById(R.id.add_new);
LinkedHashMap<Integer, String> privaciesInit = new LinkedHashMap<>(peertubeInformation.getPrivacies()); LinkedHashMap<Integer, String> privaciesInit = new LinkedHashMap<>(peertubeInformation.getPrivacies());
if (privaciesInit.size() > 0) { if (privaciesInit.size() > 0) {
@ -109,11 +116,12 @@ public class AllPlaylistsActivity extends AppCompatActivity {
playlists = new ArrayList<>(); playlists = new ArrayList<>();
ListView lv_playlist = findViewById(R.id.lv_playlist); playlistAdapter = new PlaylistAdapter(playlists, false);
playlistAdapter = new PlaylistAdapter(AllPlaylistsActivity.this, playlists, textviewNoAction); playlistAdapter.allPlaylistRemoved = this;
lv_playlist.setAdapter(playlistAdapter); binding.lvPlaylist.setAdapter(playlistAdapter);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(AllPlaylistsActivity.this);
add_new.setOnClickListener(view -> manageAlert(null)); binding.lvPlaylist.setLayoutManager(mLayoutManager);
binding.addNew.setOnClickListener(view -> manageAlert(null));
} }
@Override @Override
@ -132,7 +140,7 @@ public class AllPlaylistsActivity extends AppCompatActivity {
public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) { public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) {
mainLoader.setVisibility(View.GONE); binding.loader.setVisibility(View.GONE);
if (apiResponse.getError() != null) { if (apiResponse.getError() != null) {
Toasty.error(AllPlaylistsActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(AllPlaylistsActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
return; return;
@ -141,9 +149,9 @@ public class AllPlaylistsActivity extends AppCompatActivity {
if (apiResponse.getPlaylists() != null && apiResponse.getPlaylists().size() > 0) { if (apiResponse.getPlaylists() != null && apiResponse.getPlaylists().size() > 0) {
playlists.addAll(apiResponse.getPlaylists()); playlists.addAll(apiResponse.getPlaylists());
playlistAdapter.notifyDataSetChanged(); playlistAdapter.notifyDataSetChanged();
textviewNoAction.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE);
} else { } else {
textviewNoAction.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.VISIBLE);
} }
} }
} }
@ -152,37 +160,53 @@ public class AllPlaylistsActivity extends AppCompatActivity {
playlistToEdit = playlistParam; playlistToEdit = playlistParam;
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(AllPlaylistsActivity.this); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(AllPlaylistsActivity.this);
LayoutInflater inflater1 = getLayoutInflater(); bindingDialog = AddPlaylistBinding.inflate(LayoutInflater.from(AllPlaylistsActivity.this), null, false);
View dialogView = inflater1.inflate(R.layout.add_playlist, new LinearLayout(AllPlaylistsActivity.this), false); dialogBuilder.setView(bindingDialog.getRoot());
dialogBuilder.setView(dialogView);
EditText display_name = dialogView.findViewById(R.id.display_name); dialogBuilder.setView(bindingDialog.getRoot());
EditText description = dialogView.findViewById(R.id.description);
set_upload_channel = dialogView.findViewById(R.id.set_upload_channel);
set_upload_privacy = dialogView.findViewById(R.id.set_upload_privacy);
ChannelsVM viewModelC = new ViewModelProvider(AllPlaylistsActivity.this).get(ChannelsVM.class); ChannelsVM viewModelC = new ViewModelProvider(AllPlaylistsActivity.this).get(ChannelsVM.class);
viewModelC.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(AllPlaylistsActivity.this, this::manageVIewChannels); viewModelC.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(AllPlaylistsActivity.this, this::manageVIewChannels);
display_name.setFilters(new InputFilter[]{new InputFilter.LengthFilter(120)}); bindingDialog.displayName.setFilters(new InputFilter[]{new InputFilter.LengthFilter(120)});
description.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1000)}); bindingDialog.description.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1000)});
if (playlistToEdit != null) { if (playlistToEdit != null) {
display_name.setText(playlistToEdit.getDisplayName()); bindingDialog.displayName.setText(playlistToEdit.getDisplayName());
description.setText(playlistToEdit.getDescription()); bindingDialog.description.setText(playlistToEdit.getDescription());
} }
dialogBuilder.setPositiveButton(R.string.validate, null); dialogBuilder.setPositiveButton(R.string.validate, null);
dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alertDialog = dialogBuilder.create(); AlertDialog alertDialog = dialogBuilder.create();
bindingDialog.selectFile.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(AllPlaylistsActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(AllPlaylistsActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
return;
}
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
String[] mimetypes = {"image/*"};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, PICK_AVATAR);
});
Helper.loadGiF(AllPlaylistsActivity.this, playlistParam.getThumbnailPath(), bindingDialog.profilePicture);
alertDialog.setOnShowListener(dialogInterface -> { alertDialog.setOnShowListener(dialogInterface -> {
Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(view -> { button.setOnClickListener(view -> {
if (display_name.getText() != null && display_name.getText().toString().trim().length() > 0) { if (bindingDialog.displayName.getText() != null && bindingDialog.displayName.getText().toString().trim().length() > 0) {
PlaylistParams playlistElement = new PlaylistParams(); PlaylistParams playlistElement = new PlaylistParams();
playlistElement.setDisplayName(display_name.getText().toString().trim()); playlistElement.setDisplayName(bindingDialog.displayName.getText().toString().trim());
if (description.getText() != null && description.getText().toString().trim().length() > 0) { if (bindingDialog.description.getText() != null && bindingDialog.description.getText().toString().trim().length() > 0) {
playlistElement.setDescription(description.getText().toString().trim()); playlistElement.setDescription(bindingDialog.description.getText().toString().trim());
} }
playlistElement.setVideoChannelId(idChannel); playlistElement.setVideoChannelId(idChannel);
String label; String label;
@ -200,11 +224,11 @@ public class AllPlaylistsActivity extends AppCompatActivity {
new Thread(() -> { new Thread(() -> {
String playlistId; String playlistId;
if (playlistToEdit == null) { if (playlistToEdit == null) {
APIResponse apiResponse = new RetrofitPeertubeAPI(AllPlaylistsActivity.this).createOrUpdatePlaylist(PlaylistsVM.action.CREATE_PLAYLIST, null, playlistElement, null); APIResponse apiResponse = new RetrofitPeertubeAPI(AllPlaylistsActivity.this).createOrUpdatePlaylist(PlaylistsVM.action.CREATE_PLAYLIST, null, playlistElement, inputData);
playlistId = apiResponse.getActionReturn(); playlistId = apiResponse.getActionReturn();
} else { } else {
playlistId = playlistToEdit.getId(); playlistId = playlistToEdit.getId();
new RetrofitPeertubeAPI(AllPlaylistsActivity.this).createOrUpdatePlaylist(PlaylistsVM.action.UPDATE_PLAYLIST, playlistId, playlistElement, null); new RetrofitPeertubeAPI(AllPlaylistsActivity.this).createOrUpdatePlaylist(PlaylistsVM.action.UPDATE_PLAYLIST, playlistId, playlistElement, inputData);
} }
Handler mainHandler = new Handler(Looper.getMainLooper()); Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> { Runnable myRunnable = () -> {
@ -244,7 +268,7 @@ public class AllPlaylistsActivity extends AppCompatActivity {
//Hide keyboard //Hide keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
assert imm != null; assert imm != null;
imm.hideSoftInputFromWindow(display_name.getWindowToken(), 0); imm.hideSoftInputFromWindow(bindingDialog.displayName.getWindowToken(), 0);
}); });
if (alertDialog.getWindow() != null) if (alertDialog.getWindow() != null)
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
@ -252,6 +276,24 @@ public class AllPlaylistsActivity extends AppCompatActivity {
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_AVATAR && resultCode == Activity.RESULT_OK) {
if (data == null || data.getData() == null) {
Toasty.error(AllPlaylistsActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return;
}
inputData = data.getData();
Glide.with(AllPlaylistsActivity.this)
.load(inputData)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(bindingDialog.profilePicture);
}
}
public void manageVIewChannels(APIResponse apiResponse) { public void manageVIewChannels(APIResponse apiResponse) {
if (apiResponse.getError() != null || apiResponse.getChannels() == null || apiResponse.getChannels().size() == 0) { if (apiResponse.getError() != null || apiResponse.getChannels() == null || apiResponse.getChannels().size() == 0) {
if (apiResponse.getError() != null && apiResponse.getError().getError() != null) if (apiResponse.getError() != null && apiResponse.getError().getError() != null)
@ -277,7 +319,7 @@ public class AllPlaylistsActivity extends AppCompatActivity {
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(AllPlaylistsActivity.this, ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(AllPlaylistsActivity.this,
android.R.layout.simple_spinner_dropdown_item, channelName); android.R.layout.simple_spinner_dropdown_item, channelName);
set_upload_channel.setAdapter(adapterChannel); bindingDialog.setUploadChannel.setAdapter(adapterChannel);
LinkedHashMap<String, String> translations = null; LinkedHashMap<String, String> translations = null;
@ -305,19 +347,19 @@ public class AllPlaylistsActivity extends AppCompatActivity {
ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(AllPlaylistsActivity.this, ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(AllPlaylistsActivity.this,
android.R.layout.simple_spinner_dropdown_item, privaciesA); android.R.layout.simple_spinner_dropdown_item, privaciesA);
set_upload_privacy.setAdapter(adapterPrivacies); bindingDialog.setUploadPrivacy.setAdapter(adapterPrivacies);
if (playlistToEdit != null) { if (playlistToEdit != null) {
Item privacy = playlistToEdit.getPrivacy(); Item privacy = playlistToEdit.getPrivacy();
if (privacy.getId() > 0) { if (privacy.getId() > 0) {
set_upload_privacy.setSelection(privacy.getId() - 1); bindingDialog.setUploadPrivacy.setSelection(privacy.getId() - 1);
} }
} else { } else {
set_upload_privacy.setSelection(2); bindingDialog.setUploadPrivacy.setSelection(2);
} }
//Manage privacies //Manage privacies
set_upload_privacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { bindingDialog.setUploadPrivacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies()); LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
@ -345,12 +387,12 @@ public class AllPlaylistsActivity extends AppCompatActivity {
Item privacy = playlistToEdit.getPrivacy(); Item privacy = playlistToEdit.getPrivacy();
if (privacy.getId() > 0) { if (privacy.getId() > 0) {
set_upload_privacy.setSelection(privacy.getId() - 1); bindingDialog.setUploadPrivacy.setSelection(privacy.getId() - 1);
} }
} }
//Manage languages //Manage languages
set_upload_channel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { bindingDialog.setUploadChannel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
idChannel = channelId[position]; idChannel = channelId[position];
@ -375,7 +417,12 @@ public class AllPlaylistsActivity extends AppCompatActivity {
} }
k++; k++;
} }
set_upload_channel.setSelection(position); bindingDialog.setUploadChannel.setSelection(position);
} }
} }
@Override
public void onAllPlaylistRemoved() {
binding.noAction.setVisibility(View.VISIBLE);
}
} }

View File

@ -14,29 +14,70 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build;
import androidx.multidex.MultiDex; import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication; import androidx.multidex.MultiDexApplication;
import androidx.work.Configuration;
import androidx.work.WorkManager;
import net.gotev.uploadservice.UploadService; import net.gotev.uploadservice.UploadServiceConfig;
import net.gotev.uploadservice.observer.request.GlobalRequestObserver;
import java.util.Objects;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.helper.ThemeHelper; import app.fedilab.fedilabtube.helper.ThemeHelper;
import app.fedilab.fedilabtube.services.GlobalUploadObserver;
import app.fedilab.fedilabtube.worker.WorkHelper;
public class FedilabTube extends MultiDexApplication { public class FedilabTube extends MultiDexApplication {
static String UPLOAD_CHANNEL_ID = "upload_info_peertube";
@Override
public void onCreate() {
super.onCreate();
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int interval = sharedpreferences.getInt(Helper.NOTIFICATION_INTERVAL, 60);
Configuration myConfig = new Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.INFO)
.build();
WorkManager.initialize(FedilabTube.this, myConfig);
if (interval >= 15) {
WorkHelper.fetchNotifications(this, interval);
}
createNotificationChannel();
UploadServiceConfig.initialize(FedilabTube.this, UPLOAD_CHANNEL_ID, true);
new GlobalRequestObserver(this, new GlobalUploadObserver());
}
@Override @Override
protected void attachBaseContext(Context base) { protected void attachBaseContext(Context base) {
super.attachBaseContext(base); super.attachBaseContext(base);
MultiDex.install(FedilabTube.this); MultiDex.install(FedilabTube.this);
UploadService.NAMESPACE = BuildConfig.APPLICATION_ID;
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int themePref = sharedpreferences.getInt(Helper.SET_THEME, Helper.DEFAULT_MODE); int themePref = sharedpreferences.getInt(Helper.SET_THEME, Helper.DEFAULT_MODE);
ThemeHelper.switchTo(themePref); ThemeHelper.switchTo(themePref);
} }
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(UPLOAD_CHANNEL_ID,
getString(R.string.notification_channel_name),
NotificationManager.IMPORTANCE_LOW);
channel.setSound(null, null);
((NotificationManager) Objects.requireNonNull(getSystemService(Context.NOTIFICATION_SERVICE))).createNotificationChannel(channel);
}
}
} }

View File

@ -48,7 +48,7 @@ import app.fedilab.fedilabtube.helper.RoundedBackgroundSpan;
import app.fedilab.fedilabtube.viewmodel.InstancesVM; import app.fedilab.fedilabtube.viewmodel.InstancesVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation; import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class InstancePickerActivity extends AppCompatActivity { public class InstancePickerActivity extends AppCompatActivity {

View File

@ -0,0 +1,79 @@
package app.fedilab.fedilabtube;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import app.fedilab.fedilabtube.client.data.PlaylistData;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty;
public class LocalPlaylistsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_playlists);
PlaylistData.Playlist playlist;
Bundle b = getIntent().getExtras();
if (b != null) {
playlist = b.getParcelable("playlist");
if (playlist == null) {
return;
}
} else {
Toasty.error(LocalPlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
return;
}
setTitle(playlist.getDisplayName());
if (savedInstanceState == null) {
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.VIDEOS_IN_LOCAL_PLAYLIST);
bundle.putSerializable("playlistId", playlist.getUuid());
displayVideosFragment.setArguments(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.nav_host_fragment, displayVideosFragment).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -22,20 +22,18 @@ import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan; import android.text.style.UnderlineSpan;
import android.util.Patterns;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.google.android.material.textfield.TextInputEditText; import java.net.MalformedURLException;
import com.google.android.material.textfield.TextInputLayout; import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
@ -43,6 +41,7 @@ import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.Oauth; import app.fedilab.fedilabtube.client.entities.Oauth;
import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.OauthParams;
import app.fedilab.fedilabtube.client.entities.Token; import app.fedilab.fedilabtube.client.entities.Token;
import app.fedilab.fedilabtube.databinding.ActivityLoginBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@ -54,29 +53,26 @@ public class LoginActivity extends AppCompatActivity {
private static String client_id; private static String client_id;
private static String client_secret; private static String client_secret;
private EditText login_uid; private ActivityLoginBinding binding;
private EditText login_passwd;
private Button connectionButton;
private TextInputEditText login_instance;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityLoginBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
setContentView(R.layout.activity_login);
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
TextView create_an_account_peertube = findViewById(R.id.create_an_account_peertube);
SpannableString content_create = new SpannableString(getString(R.string.join_peertube)); SpannableString content_create = new SpannableString(getString(R.string.join_peertube));
content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0); content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0);
content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, Helper.getColorAccent())), 0, content_create.length(), content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, Helper.getColorAccent())), 0, content_create.length(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE); Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
create_an_account_peertube.setText(content_create); binding.createAnAccountPeertube.setText(content_create, TextView.BufferType.SPANNABLE);
create_an_account_peertube.setOnClickListener(v -> { binding.createAnAccountPeertube.setOnClickListener(v -> {
Intent mainActivity = new Intent(LoginActivity.this, PeertubeRegisterActivity.class); Intent mainActivity = new Intent(LoginActivity.this, PeertubeRegisterActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
mainActivity.putExtras(b); mainActivity.putExtras(b);
@ -84,42 +80,34 @@ public class LoginActivity extends AppCompatActivity {
}); });
TextInputLayout login_instance_container = findViewById(R.id.login_instance_container);
login_instance = findViewById(R.id.login_instance);
if (BuildConfig.full_instances) { if (BuildConfig.full_instances) {
login_instance_container.setVisibility(View.VISIBLE); binding.loginInstanceContainer.setVisibility(View.VISIBLE);
} }
login_uid = findViewById(R.id.login_uid);
login_passwd = findViewById(R.id.login_passwd);
if (Helper.isTablet(LoginActivity.this)) { if (Helper.isTablet(LoginActivity.this)) {
ViewGroup.LayoutParams layoutParamsI = login_instance_container.getLayoutParams(); ViewGroup.LayoutParams layoutParamsI = binding.loginInstanceContainer.getLayoutParams();
layoutParamsI.width = (int) Helper.convertDpToPixel(300, LoginActivity.this); layoutParamsI.width = (int) Helper.convertDpToPixel(300, LoginActivity.this);
login_instance_container.setLayoutParams(layoutParamsI); binding.loginInstanceContainer.setLayoutParams(layoutParamsI);
TextInputLayout login_uid_container = findViewById(R.id.login_uid_container); ViewGroup.LayoutParams layoutParamsU = binding.loginUidContainer.getLayoutParams();
ViewGroup.LayoutParams layoutParamsU = login_uid_container.getLayoutParams();
layoutParamsU.width = (int) Helper.convertDpToPixel(300, LoginActivity.this); layoutParamsU.width = (int) Helper.convertDpToPixel(300, LoginActivity.this);
login_uid_container.setLayoutParams(layoutParamsU); binding.loginUidContainer.setLayoutParams(layoutParamsU);
TextInputLayout login_passwd_container = findViewById(R.id.login_passwd_container); ViewGroup.LayoutParams layoutParamsP = binding.loginPasswdContainer.getLayoutParams();
ViewGroup.LayoutParams layoutParamsP = login_passwd_container.getLayoutParams();
layoutParamsP.width = (int) Helper.convertDpToPixel(300, LoginActivity.this); layoutParamsP.width = (int) Helper.convertDpToPixel(300, LoginActivity.this);
login_passwd_container.setLayoutParams(layoutParamsP); binding.loginPasswdContainer.setLayoutParams(layoutParamsP);
} }
connectionButton = findViewById(R.id.login_button);
if (!BuildConfig.full_instances) { if (!BuildConfig.full_instances) {
login_uid.setOnFocusChangeListener((v, hasFocus) -> { binding.loginUid.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) { if (!hasFocus) {
if (android.util.Patterns.EMAIL_ADDRESS.matcher(login_uid.getText().toString().trim()).matches()) { if (binding.loginUid.getText() != null && android.util.Patterns.EMAIL_ADDRESS.matcher(binding.loginUid.getText().toString().trim()).matches()) {
String[] emailArray = login_uid.getText().toString().split("@"); String[] emailArray = binding.loginUid.getText().toString().split("@");
if (emailArray.length > 1 && Arrays.asList(Helper.openid).contains(emailArray[1])) { if (emailArray.length > 1 && Arrays.asList(Helper.openid).contains(emailArray[1])) {
connectionButton.callOnClick(); binding.loginButton.callOnClick();
} }
} }
} }
@ -127,38 +115,63 @@ public class LoginActivity extends AppCompatActivity {
} }
connectionButton.setOnClickListener(v -> { binding.loginButton.setOnClickListener(v -> {
if (login_uid.getText().toString().contains("@") && !android.util.Patterns.EMAIL_ADDRESS.matcher(login_uid.getText().toString().trim()).matches()) { if (binding.loginUid.getText() != null && binding.loginUid.getText().toString().contains("@") && !android.util.Patterns.EMAIL_ADDRESS.matcher(binding.loginUid.getText().toString().trim()).matches()) {
Toasty.error(LoginActivity.this, getString(R.string.email_error)).show(); Toasty.error(LoginActivity.this, getString(R.string.email_error)).show();
return; return;
} }
connectionButton.setEnabled(false); binding.loginButton.setEnabled(false);
String instance, host; String instance, host;
if (!BuildConfig.full_instances) { if (!BuildConfig.full_instances) {
String[] emailArray = login_uid.getText().toString().split("@"); String[] emailArray = binding.loginUid.getText().toString().split("@");
if (emailArray.length > 1 && !Arrays.asList(Helper.valideEmails).contains(emailArray[1])) { if (emailArray.length > 1 && !Arrays.asList(Helper.valideEmails).contains(emailArray[1])) {
Toasty.error(LoginActivity.this, getString(R.string.email_error_domain, emailArray[1])).show(); Toasty.error(LoginActivity.this, getString(R.string.email_error_domain, emailArray[1])).show();
connectionButton.setEnabled(true); binding.loginButton.setEnabled(true);
return; return;
} }
host = emailArray[1]; host = emailArray[1];
instance = Helper.getPeertubeUrl(host); instance = Helper.getPeertubeUrl(host);
} else { } else {
if (login_instance == null || login_instance.getText() == null || login_instance.getText().toString().trim().length() == 0) { if (binding.loginInstance.getText() == null || binding.loginInstance.getText().toString().trim().length() == 0) {
Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show(); Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show();
connectionButton.setEnabled(true); binding.loginButton.setEnabled(true);
return; return;
} }
instance = host = login_instance.getText().toString().trim().toLowerCase(); instance = host = binding.loginInstance.getText().toString().trim().toLowerCase();
} }
if (instance.startsWith("http")) {
try {
URL url = new URL(instance);
instance = url.getHost();
host = instance;
} catch (MalformedURLException e) {
e.printStackTrace();
}
} else if (instance.endsWith("/")) {
try {
URL url = new URL("https://" + instance);
instance = url.getHost();
host = instance;
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
if (!Patterns.WEB_URL.matcher("https://" + instance).matches()) {
Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show();
binding.loginButton.setEnabled(true);
return;
}
String finalInstance = instance;
String finalHost = host;
if (Arrays.asList(Helper.openid).contains(host) && !BuildConfig.full_instances) { if (Arrays.asList(Helper.openid).contains(host) && !BuildConfig.full_instances) {
new Thread(() -> { new Thread(() -> {
try { try {
Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).oauthClient(null, null, null, null); Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(null, null, null, null);
if (oauth == null) { if (oauth == null) {
runOnUiThread(() -> { runOnUiThread(() -> {
connectionButton.setEnabled(true); binding.loginButton.setEnabled(true);
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
}); });
return; return;
@ -172,14 +185,14 @@ public class LoginActivity extends AppCompatActivity {
editor.apply(); editor.apply();
Intent intent = new Intent(LoginActivity.this, WebviewConnectActivity.class); Intent intent = new Intent(LoginActivity.this, WebviewConnectActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putString("url", "https://" + Helper.getPeertubeUrl(host) + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect"); b.putString("url", "https://" + Helper.getPeertubeUrl(finalHost) + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect");
intent.putExtras(b); intent.putExtras(b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); startActivity(intent);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
runOnUiThread(() -> { runOnUiThread(() -> {
connectionButton.setEnabled(true); binding.loginButton.setEnabled(true);
Toasty.error(LoginActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); Toasty.error(LoginActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}); });
} }
@ -187,10 +200,10 @@ public class LoginActivity extends AppCompatActivity {
}).start(); }).start();
} else { } else {
new Thread(() -> { new Thread(() -> {
Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.WEBSITE_VALUE, Helper.OAUTH_SCOPES_PEERTUBE, Helper.WEBSITE_VALUE); Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.WEBSITE_VALUE, Helper.OAUTH_SCOPES_PEERTUBE, Helper.WEBSITE_VALUE);
if (oauth == null) { if (oauth == null) {
runOnUiThread(() -> { runOnUiThread(() -> {
connectionButton.setEnabled(true); binding.loginButton.setEnabled(true);
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
}); });
return; return;
@ -209,20 +222,22 @@ public class LoginActivity extends AppCompatActivity {
oauthParams.setClient_secret(client_secret); oauthParams.setClient_secret(client_secret);
oauthParams.setGrant_type("password"); oauthParams.setGrant_type("password");
oauthParams.setScope("user"); oauthParams.setScope("user");
oauthParams.setUsername(login_uid.getText().toString().trim()); oauthParams.setUsername(binding.loginUid.getText().toString().trim());
oauthParams.setPassword(login_passwd.getText().toString()); if (binding.loginPasswd.getText() != null) {
oauthParams.setPassword(binding.loginPasswd.getText().toString());
}
try { try {
Token token = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).manageToken(oauthParams); Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams);
proceedLogin(token, host); proceedLogin(token, finalHost);
} catch (final Exception | Error e) { } catch (final Exception | Error e) {
oauthParams.setUsername(login_uid.getText().toString().toLowerCase().trim()); oauthParams.setUsername(binding.loginUid.getText().toString().toLowerCase().trim());
try { try {
Token token = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).manageToken(oauthParams); Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams);
proceedLogin(token, host); proceedLogin(token, finalHost);
} catch (Error error) { } catch (Error error) {
Error.displayError(LoginActivity.this, error); Error.displayError(LoginActivity.this, error);
error.printStackTrace(); error.printStackTrace();
runOnUiThread(() -> connectionButton.setEnabled(true)); runOnUiThread(() -> binding.loginButton.setEnabled(true));
} }
} }
}).start(); }).start();
@ -243,7 +258,7 @@ public class LoginActivity extends AppCompatActivity {
//Update the account with the token; //Update the account with the token;
updateCredential(LoginActivity.this, token.getAccess_token(), client_id, client_secret, token.getRefresh_token(), host); updateCredential(LoginActivity.this, token.getAccess_token(), client_id, client_secret, token.getRefresh_token(), host);
} else { } else {
connectionButton.setEnabled(true); binding.loginButton.setEnabled(true);
} }
}); });
} }

View File

@ -20,13 +20,17 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -35,6 +39,9 @@ import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.kobakei.ratethisapp.RateThisApp; import com.kobakei.ratethisapp.RateThisApp;
@ -45,97 +52,165 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.AccountData.Account; import app.fedilab.fedilabtube.client.data.AccountData.Account;
import app.fedilab.fedilabtube.client.data.InstanceData;
import app.fedilab.fedilabtube.client.entities.Error; import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.OauthParams;
import app.fedilab.fedilabtube.client.entities.PeertubeInformation; import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
import app.fedilab.fedilabtube.client.entities.Token; import app.fedilab.fedilabtube.client.entities.Token;
import app.fedilab.fedilabtube.client.entities.UserMe; import app.fedilab.fedilabtube.client.entities.UserMe;
import app.fedilab.fedilabtube.client.entities.UserSettings;
import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo;
import app.fedilab.fedilabtube.databinding.ActivityMainBinding;
import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment; import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
import app.fedilab.fedilabtube.helper.SwitchAccountHelper;
import app.fedilab.fedilabtube.services.RetrieveInfoService; import app.fedilab.fedilabtube.services.RetrieveInfoService;
import app.fedilab.fedilabtube.sqlite.AccountDAO; import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.sqlite.StoredInstanceDAO;
import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.NORMAL;
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.SURFING;
import static app.fedilab.fedilabtube.helper.Helper.academies; import static app.fedilab.fedilabtube.helper.Helper.academies;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
public static PeertubeInformation peertubeInformation;
public static int PICK_INSTANCE = 5641; public static int PICK_INSTANCE = 5641;
final FragmentManager fm = getSupportFragmentManager(); public static int PICK_INSTANCE_SURF = 5642;
Fragment active; public static UserMe userMe;
public static InstanceData.InstanceConfig instanceConfig;
public static TypeOfConnection typeOfConnection;
private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment; private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
private DisplayOverviewFragment overviewFragment; private DisplayOverviewFragment overviewFragment;
private ActivityMainBinding binding;
@SuppressLint("ApplySharedPref")
public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) {
final SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(activity);
alt_bld.setTitle(R.string.instance_choice);
String instance = Helper.getLiveInstance(activity);
final EditText input = new EditText(activity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
alt_bld.setView(input);
input.setText(instance);
alt_bld.setPositiveButton(R.string.validate,
(dialog, which) -> new Thread(() -> {
try {
String newInstance = input.getText().toString().trim();
WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(activity, newInstance, null).getNodeInfo();
if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("peertube") == 0) {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_INSTANCE, newInstance);
editor.commit();
if (storeInDb) {
newInstance = newInstance.trim().toLowerCase();
InstanceData.AboutInstance aboutInstance = new RetrofitPeertubeAPI(activity, newInstance, null).getAboutInstance();
SQLiteDatabase db = Sqlite.getInstance(activity.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new StoredInstanceDAO(activity, db).insertInstance(aboutInstance, newInstance);
activity.runOnUiThread(() -> {
dialog.dismiss();
Helper.logoutNoRemoval(activity);
});
} else {
activity.runOnUiThread(() -> {
dialog.dismiss();
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
});
}
} else {
activity.runOnUiThread(() -> Toasty.error(activity, activity.getString(R.string.not_valide_instance), Toast.LENGTH_LONG).show());
}
} catch (Exception e) {
e.printStackTrace();
}
}).start());
alt_bld.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
alt_bld.setNeutralButton(R.string.help, (dialog, which) -> {
Intent intent = new Intent(activity, InstancePickerActivity.class);
if (storeInDb) {
activity.startActivityForResult(intent, PICK_INSTANCE_SURF);
} else {
activity.startActivityForResult(intent, PICK_INSTANCE);
}
});
AlertDialog alert = alt_bld.create();
alert.show();
}
private void setTitleCustom(int titleRId) {
Toolbar toolbar = findViewById(R.id.toolbar);
TextView mTitle = toolbar.findViewById(R.id.toolbar_title);
if (mTitle != null) {
mTitle.setText(getString(titleRId));
}
}
private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= item -> { = item -> {
DisplayVideosFragment displayVideosFragment = null;
int itemId = item.getItemId(); int itemId = item.getItemId();
if (itemId == R.id.navigation_subscription) { if (itemId == R.id.navigation_discover) {
displayVideosFragment = subscriptionFragment; setTitleCustom(R.string.title_discover);
setTitle(R.string.subscriptions); binding.viewpager.setCurrentItem(0);
} else if (itemId == R.id.navigation_subscription) {
binding.viewpager.setCurrentItem(1);
setTitleCustom(R.string.subscriptions);
} else if (itemId == R.id.navigation_trending) { } else if (itemId == R.id.navigation_trending) {
setTitle(R.string.title_trending); setTitleCustom(R.string.title_trending);
displayVideosFragment = trendingFragment; if (Helper.isLoggedIn(MainActivity.this)) {
binding.viewpager.setCurrentItem(2);
} else {
binding.viewpager.setCurrentItem(1);
}
} else if (itemId == R.id.navigation_most_liked) { } else if (itemId == R.id.navigation_most_liked) {
setTitle(R.string.title_most_liked); setTitleCustom(R.string.title_most_liked);
displayVideosFragment = mostLikedFragment; binding.viewpager.setCurrentItem(2);
} else if (itemId == R.id.navigation_recently_added) { } else if (itemId == R.id.navigation_recently_added) {
setTitle(R.string.title_recently_added); setTitleCustom(R.string.title_recently_added);
displayVideosFragment = recentFragment; binding.viewpager.setCurrentItem(3);
} else if (itemId == R.id.navigation_local) { } else if (itemId == R.id.navigation_local) {
setTitle(R.string.title_local); setTitleCustom(R.string.title_local);
displayVideosFragment = locaFragment; binding.viewpager.setCurrentItem(4);
} else if (itemId == R.id.navigation_discover) {
setTitle(R.string.title_discover);
fm.beginTransaction().hide(active).show(overviewFragment).commit();
active = overviewFragment;
return true;
}
if (displayVideosFragment != null) {
fm.beginTransaction().hide(active).show(displayVideosFragment).commit();
active = displayVideosFragment;
return true;
} else {
return false;
} }
return true;
}; };
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
typeOfConnection = TypeOfConnection.UNKNOWN;
BottomNavigationView navView = findViewById(R.id.nav_view); BottomNavigationView navView = findViewById(R.id.nav_view);
navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
Fragment fragment = getSupportFragmentManager().findFragmentByTag("5"); if (getSupportActionBar() != null) {
if (fragment != null) getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportFragmentManager().beginTransaction().remove(fragment).commit(); }
fragment = getSupportFragmentManager().findFragmentByTag("4"); checkIfConnectedUsers();
if (fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
fragment = getSupportFragmentManager().findFragmentByTag("3");
if (fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
fragment = getSupportFragmentManager().findFragmentByTag("2");
if (fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
fragment = getSupportFragmentManager().findFragmentByTag("1");
if (fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
recentFragment = new DisplayVideosFragment(); recentFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
@ -163,86 +238,46 @@ public class MainActivity extends AppCompatActivity {
mostLikedFragment.setArguments(bundle); mostLikedFragment.setArguments(bundle);
overviewFragment = new DisplayOverviewFragment(); overviewFragment = new DisplayOverviewFragment();
if (active == null) {
active = overviewFragment;
}
fm.beginTransaction().add(R.id.nav_host_fragment, locaFragment, "5").hide(locaFragment).commit();
if (!Helper.isLoggedIn(MainActivity.this)) { if (!Helper.isLoggedIn(MainActivity.this)) {
fm.beginTransaction().add(R.id.nav_host_fragment, recentFragment, "4").hide(recentFragment).commit(); PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
fm.beginTransaction().add(R.id.nav_host_fragment, mostLikedFragment, "3").hide(mostLikedFragment).commit(); binding.viewpager.setAdapter(mPagerAdapter);
fm.beginTransaction().add(R.id.nav_host_fragment, trendingFragment, "2").hide(trendingFragment).commit();
fm.beginTransaction().add(R.id.nav_host_fragment, overviewFragment, "1").commit();
} }
toolbar.setOnClickListener(v -> { binding.viewpager.setOffscreenPageLimit(5);
if (active instanceof DisplayVideosFragment) {
((DisplayVideosFragment) active).scrollToTop();
} else if (active instanceof DisplayOverviewFragment) { binding.viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
((DisplayOverviewFragment) active).scrollToTop(); @Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
MenuItem item = binding.navView.getMenu().getItem(position);
binding.navView.setSelectedItemId(item.getItemId());
}
@Override
public void onPageScrollStateChanged(int state) {
} }
}); });
setTitle(R.string.title_discover);
toolbar.setOnClickListener(v -> {
if (binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem()) instanceof DisplayVideosFragment) {
((DisplayVideosFragment) binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem())).scrollToTop();
} else if (binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem()) instanceof DisplayOverviewFragment) {
((DisplayOverviewFragment) binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem())).scrollToTop();
}
});
setTitleCustom(R.string.title_discover);
if (Helper.isLoggedIn(MainActivity.this)) { if (Helper.isLoggedIn(MainActivity.this)) {
navView.inflateMenu(R.menu.bottom_nav_menu_connected); navView.inflateMenu(R.menu.bottom_nav_menu_connected);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); refreshToken();
String tokenStr = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
String instance = Helper.getLiveInstance(MainActivity.this);
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Account account = new AccountDAO(MainActivity.this, db).getAccountByToken(tokenStr);
if (account != null) {
OauthParams oauthParams = new OauthParams();
oauthParams.setGrant_type("refresh_token");
oauthParams.setClient_id(account.getClient_id());
oauthParams.setClient_secret(account.getClient_secret());
oauthParams.setRefresh_token(account.getRefresh_token());
oauthParams.setAccess_token(account.getToken());
new Thread(() -> {
try {
Token token = new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams);
if (token == null) {
runOnUiThread(() -> Helper.logoutCurrentUser(MainActivity.this, account));
return;
}
runOnUiThread(() -> {
//To avoid a token issue with subscriptions, adding fragment is done when the token is refreshed.
new Handler().post(() -> {
fm.beginTransaction().add(R.id.nav_host_fragment, recentFragment, "4").hide(recentFragment).commitAllowingStateLoss();
fm.beginTransaction().add(R.id.nav_host_fragment, trendingFragment, "3").hide(trendingFragment).commitAllowingStateLoss();
fm.beginTransaction().add(R.id.nav_host_fragment, subscriptionFragment, "2").hide(subscriptionFragment).commitAllowingStateLoss();
fm.beginTransaction().add(R.id.nav_host_fragment, overviewFragment, "1").commitAllowingStateLoss();
});
});
UserMe userMe = new RetrofitPeertubeAPI(MainActivity.this, instance, token.getAccess_token()).verifyCredentials();
if (userMe != null && userMe.getAccount() != null) {
new AccountDAO(MainActivity.this, db).updateAccount(userMe.getAccount());
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_KEY_ID, account.getId());
editor.putString(Helper.PREF_KEY_NAME, account.getUsername());
//Sync languages from server
List<String> videoLanguageServer = userMe.getVideoLanguages();
if (videoLanguageServer != null) {
Set<String> videoLanguageServerSet = new TreeSet<>(videoLanguageServer);
videoLanguageServerSet.addAll(videoLanguageServer);
Set<String> videoLanguageLocal = sharedpreferences.getStringSet(getString(R.string.set_video_language_choice), null);
if (videoLanguageServerSet.size() > 0 && videoLanguageLocal != null) {
videoLanguageServer.addAll(videoLanguageLocal);
}
editor.putStringSet(getString(R.string.set_video_language_choice), videoLanguageServerSet);
editor.apply();
}
}
} catch (Error error) {
runOnUiThread(() -> Helper.logoutCurrentUser(MainActivity.this, account));
error.printStackTrace();
}
}).start();
}
} else { } else {
navView.inflateMenu(R.menu.bottom_nav_menu); navView.inflateMenu(R.menu.bottom_nav_menu);
@ -260,7 +295,13 @@ public class MainActivity extends AppCompatActivity {
RateThisApp.onCreate(this); RateThisApp.onCreate(this);
RateThisApp.showRateDialogIfNeeded(this); RateThisApp.showRateDialogIfNeeded(this);
} }
if (!BuildConfig.full_instances) {
PlaylistExportHelper.manageIntentUrl(MainActivity.this, getIntent());
}
}
public DisplayVideosFragment getSubscriptionFragment() {
return subscriptionFragment;
} }
private void startInForeground() { private void startInForeground() {
@ -272,6 +313,91 @@ public class MainActivity extends AppCompatActivity {
} }
} }
private void refreshToken() {
new Thread(() -> {
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String tokenStr = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
String instance = Helper.getLiveInstance(MainActivity.this);
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String instanceShar = sharedpreferences.getString(Helper.PREF_INSTANCE, null);
String userIdShar = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
Account account = new AccountDAO(MainActivity.this, db).getAccountByToken(tokenStr);
if (account == null) {
account = new AccountDAO(MainActivity.this, db).getAccountByIdInstance(userIdShar, instanceShar);
}
if (account != null) {
Account finalAccount = account;
OauthParams oauthParams = new OauthParams();
oauthParams.setGrant_type("refresh_token");
oauthParams.setClient_id(account.getClient_id());
oauthParams.setClient_secret(account.getClient_secret());
oauthParams.setRefresh_token(account.getRefresh_token());
oauthParams.setAccess_token(account.getToken());
try {
Token token = new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams);
if (token == null && Helper.instanceOnline(instance)) {
runOnUiThread(() -> {
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(R.string.refresh_token_failed);
alt_bld.setMessage(R.string.refresh_token_failed_message);
alt_bld.setNegativeButton(R.string.action_logout, (dialog, id) -> {
dialog.dismiss();
Helper.logoutCurrentUser(MainActivity.this, finalAccount);
});
alt_bld.setPositiveButton(R.string._retry, (dialog, id) -> {
dialog.dismiss();
refreshToken();
});
AlertDialog alert = alt_bld.create();
alert.show();
});
return;
} else if (token == null) {
return;
}
runOnUiThread(() -> {
//To avoid a token issue with subscriptions, adding fragment is done when the token is refreshed.
new Handler().post(() -> {
if (Helper.isLoggedIn(MainActivity.this)) {
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
binding.viewpager.setAdapter(mPagerAdapter);
}
});
});
userMe = new RetrofitPeertubeAPI(MainActivity.this, instance, token.getAccess_token()).verifyCredentials();
if (userMe != null && userMe.getAccount() != null) {
new AccountDAO(MainActivity.this, db).updateAccount(userMe.getAccount());
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_KEY_ID, account.getId());
editor.putString(Helper.PREF_KEY_NAME, account.getUsername());
editor.putBoolean(getString(R.string.set_autoplay_choice), userMe.isAutoPlayVideo());
editor.putBoolean(getString(R.string.set_store_in_history), userMe.isVideosHistoryEnabled());
editor.putBoolean(getString(R.string.set_autoplay_next_video_choice), userMe.isAutoPlayNextVideo());
editor.putString(getString(R.string.set_video_sensitive_choice), userMe.getNsfwPolicy());
//Sync languages from server
List<String> videoLanguageServer = userMe.getVideoLanguages();
if (videoLanguageServer != null) {
Set<String> videoLanguageServerSet = new TreeSet<>(videoLanguageServer);
videoLanguageServerSet.addAll(videoLanguageServer);
Set<String> videoLanguageLocal = sharedpreferences.getStringSet(getString(R.string.set_video_language_choice), null);
if (videoLanguageServerSet.size() > 0 && videoLanguageLocal != null) {
videoLanguageServer.addAll(videoLanguageLocal);
}
editor.putStringSet(getString(R.string.set_video_language_choice), videoLanguageServerSet);
editor.apply();
}
}
instanceConfig = new RetrofitPeertubeAPI(MainActivity.this).getConfigInstance();
} catch (Error error) {
runOnUiThread(() -> Helper.logoutCurrentUser(MainActivity.this, finalAccount));
error.printStackTrace();
}
}
}).start();
}
@Override @Override
public boolean onCreateOptionsMenu(@NotNull Menu menu) { public boolean onCreateOptionsMenu(@NotNull Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu); getMenuInflater().inflate(R.menu.main_menu, menu);
@ -281,6 +407,15 @@ public class MainActivity extends AppCompatActivity {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String query) { public boolean onQueryTextSubmit(String query) {
Pattern link = Pattern.compile("(https?://[\\da-z.-]+\\.[a-z.]{2,10})/videos/watch/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
Matcher matcherLink = link.matcher(query.trim());
if (matcherLink.find()) {
Intent intent = new Intent(MainActivity.this, PeertubeActivity.class);
intent.setData(Uri.parse(query.trim()));
startActivity(intent);
myActionMenuItem.collapseActionView();
return false;
}
Intent intent = new Intent(MainActivity.this, SearchActivity.class); Intent intent = new Intent(MainActivity.this, SearchActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
String search = query.trim(); String search = query.trim();
@ -299,7 +434,7 @@ public class MainActivity extends AppCompatActivity {
return false; return false;
} }
}); });
MenuItem instanceItem = menu.findItem(R.id.action_change_instance);
MenuItem uploadItem = menu.findItem(R.id.action_upload); MenuItem uploadItem = menu.findItem(R.id.action_upload);
MenuItem myVideosItem = menu.findItem(R.id.action_myvideos); MenuItem myVideosItem = menu.findItem(R.id.action_myvideos);
MenuItem playslistItem = menu.findItem(R.id.action_playlist); MenuItem playslistItem = menu.findItem(R.id.action_playlist);
@ -307,35 +442,105 @@ public class MainActivity extends AppCompatActivity {
MenuItem mostLikedItem = menu.findItem(R.id.action_most_liked); MenuItem mostLikedItem = menu.findItem(R.id.action_most_liked);
MenuItem settingsItem = menu.findItem(R.id.action_settings); MenuItem settingsItem = menu.findItem(R.id.action_settings);
MenuItem sepiaSearchItem = menu.findItem(R.id.action_sepia_search); MenuItem sepiaSearchItem = menu.findItem(R.id.action_sepia_search);
if (Helper.isLoggedIn(MainActivity.this)) { MenuItem incognitoItem = menu.findItem(R.id.action_incognito);
instanceItem.setVisible(false); MenuItem instanceItem = menu.findItem(R.id.action_change_instance);
uploadItem.setVisible(true); MenuItem accountItem = menu.findItem(R.id.action_account);
myVideosItem.setVisible(true);
playslistItem.setVisible(true); Toolbar toolbar = findViewById(R.id.toolbar);
historyItem.setVisible(true); ImageView instances = toolbar.findViewById(R.id.instances);
settingsItem.setVisible(false); if (BuildConfig.full_instances && ((Helper.isLoggedIn(MainActivity.this) && typeOfConnection == NORMAL) || typeOfConnection == SURFING)) {
mostLikedItem.setVisible(true); instances.setVisibility(View.VISIBLE);
instances.setOnClickListener(null);
instances.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, ManageInstancesActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up);
});
} else { } else {
instanceItem.setVisible(true); instances.setVisibility(View.GONE);
uploadItem.setVisible(false);
myVideosItem.setVisible(false);
playslistItem.setVisible(false);
historyItem.setVisible(false);
settingsItem.setVisible(true);
mostLikedItem.setVisible(false);
} }
switch (typeOfConnection) {
case UNKNOWN:
instanceItem.setVisible(false);
accountItem.setVisible(false);
uploadItem.setVisible(false);
myVideosItem.setVisible(false);
playslistItem.setVisible(false);
historyItem.setVisible(false);
settingsItem.setVisible(false);
mostLikedItem.setVisible(false);
incognitoItem.setVisible(false);
break;
case NORMAL:
accountItem.setVisible(true);
if (Helper.isLoggedIn(MainActivity.this)) {
instanceItem.setVisible(false);
uploadItem.setVisible(true);
myVideosItem.setVisible(true);
playslistItem.setVisible(true);
historyItem.setVisible(true);
settingsItem.setVisible(false);
mostLikedItem.setVisible(true);
incognitoItem.setVisible(true);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean checked = sharedpreferences.getBoolean(getString(R.string.set_store_in_history), true);
incognitoItem.setChecked(checked);
} else {
instanceItem.setVisible(true);
uploadItem.setVisible(false);
myVideosItem.setVisible(false);
playslistItem.setVisible(!BuildConfig.full_instances);
historyItem.setVisible(false);
settingsItem.setVisible(true);
mostLikedItem.setVisible(false);
incognitoItem.setVisible(false);
}
break;
case SURFING:
instanceItem.setVisible(false);
accountItem.setVisible(true);
uploadItem.setVisible(false);
myVideosItem.setVisible(false);
playslistItem.setVisible(false);
historyItem.setVisible(false);
settingsItem.setVisible(false);
mostLikedItem.setVisible(false);
incognitoItem.setVisible(false);
break;
}
if (!BuildConfig.full_instances) { if (!BuildConfig.full_instances) {
sepiaSearchItem.setVisible(false); sepiaSearchItem.setVisible(false);
} }
return true; return true;
} }
private void checkIfConnectedUsers() {
new Thread(() -> {
try {
typeOfConnection = NORMAL;
if (!Helper.isLoggedIn(MainActivity.this)) {
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<Account> accounts = new AccountDAO(MainActivity.this, db).getAllAccount();
if (accounts != null && accounts.size() > 0) {
//The user is not authenticated and there accounts in db. That means the user is surfing some other instances
typeOfConnection = TypeOfConnection.SURFING;
}
}
runOnUiThread(this::invalidateOptionsMenu);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_change_instance) { if (item.getItemId() == R.id.action_change_instance) {
if (BuildConfig.full_instances) { if (BuildConfig.full_instances) {
showRadioButtonDialogFullInstances(); showRadioButtonDialogFullInstances(MainActivity.this, false);
} else { } else {
showRadioButtonDialog(); showRadioButtonDialog();
} }
@ -345,12 +550,16 @@ public class MainActivity extends AppCompatActivity {
startActivity(intent); startActivity(intent);
} else if (item.getItemId() == R.id.action_account) { } else if (item.getItemId() == R.id.action_account) {
Intent intent; Intent intent;
if (Helper.isLoggedIn(MainActivity.this)) { if (typeOfConnection == SURFING) {
intent = new Intent(MainActivity.this, AccountActivity.class); SwitchAccountHelper.switchDialog(MainActivity.this, false);
} else { } else {
intent = new Intent(MainActivity.this, LoginActivity.class); if (Helper.isLoggedIn(MainActivity.this)) {
intent = new Intent(MainActivity.this, AccountActivity.class);
} else {
intent = new Intent(MainActivity.this, LoginActivity.class);
}
startActivity(intent);
} }
startActivity(intent);
return true; return true;
} else if (item.getItemId() == R.id.action_upload) { } else if (item.getItemId() == R.id.action_upload) {
Intent intent = new Intent(MainActivity.this, PeertubeUploadActivity.class); Intent intent = new Intent(MainActivity.this, PeertubeUploadActivity.class);
@ -378,7 +587,12 @@ public class MainActivity extends AppCompatActivity {
startActivity(intent); startActivity(intent);
return true; return true;
} else if (item.getItemId() == R.id.action_playlist) { } else if (item.getItemId() == R.id.action_playlist) {
Intent intent = new Intent(MainActivity.this, AllPlaylistsActivity.class); Intent intent;
if (Helper.isLoggedIn(MainActivity.this)) {
intent = new Intent(MainActivity.this, AllPlaylistsActivity.class);
} else {
intent = new Intent(MainActivity.this, AllLocalPlaylistsActivity.class);
}
startActivity(intent); startActivity(intent);
return true; return true;
} else if (item.getItemId() == R.id.action_sepia_search) { } else if (item.getItemId() == R.id.action_sepia_search) {
@ -389,17 +603,28 @@ public class MainActivity extends AppCompatActivity {
Intent intent = new Intent(MainActivity.this, AboutActivity.class); Intent intent = new Intent(MainActivity.this, AboutActivity.class);
startActivity(intent); startActivity(intent);
return true; return true;
} else if (item.getItemId() == R.id.action_incognito) {
item.setChecked(!item.isChecked());
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean(getString(R.string.set_store_in_history), item.isChecked());
editor.apply();
new Thread(() -> {
UserSettings userSettings = new UserSettings();
userSettings.setVideosHistoryEnabled(item.isChecked());
try {
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(MainActivity.this);
api.updateUser(userSettings);
} catch (Exception | Error e) {
e.printStackTrace();
}
}).start();
return false;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
public void setActive(DisplayVideosFragment displayVideosFragment) {
this.active = displayVideosFragment;
}
public void setSubscriptionFragment(DisplayVideosFragment displayVideosFragment) {
this.subscriptionFragment = displayVideosFragment;
}
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
@ -411,9 +636,12 @@ public class MainActivity extends AppCompatActivity {
if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) { if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) {
recreate(); recreate();
} }
} else if (!BuildConfig.full_instances) {
PlaylistExportHelper.manageIntentUrl(MainActivity.this, intent);
} }
} }
@SuppressLint("ApplySharedPref") @SuppressLint("ApplySharedPref")
private void showRadioButtonDialog() { private void showRadioButtonDialog() {
@ -441,50 +669,6 @@ public class MainActivity extends AppCompatActivity {
alert.show(); alert.show();
} }
@SuppressLint("ApplySharedPref")
private void showRadioButtonDialogFullInstances() {
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(R.string.instance_choice);
String instance = Helper.getLiveInstance(MainActivity.this);
final EditText input = new EditText(MainActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
alt_bld.setView(input);
input.setText(instance);
alt_bld.setPositiveButton(R.string.validate,
(dialog, which) -> new Thread(() -> {
try {
String newInstance = input.getText().toString().trim();
WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(MainActivity.this, newInstance, null).getNodeInfo();
if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("peertube") == 0) {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_INSTANCE, newInstance);
editor.commit();
runOnUiThread(() -> {
dialog.dismiss();
recreate();
});
} else {
runOnUiThread(() -> Toasty.error(MainActivity.this, getString(R.string.not_valide_instance), Toast.LENGTH_LONG).show());
}
} catch (Exception e) {
e.printStackTrace();
}
}).start());
alt_bld.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
alt_bld.setNeutralButton(R.string.help, (dialog, which) -> {
Intent intent = new Intent(MainActivity.this, InstancePickerActivity.class);
startActivityForResult(intent, PICK_INSTANCE);
});
AlertDialog alert = alt_bld.create();
alert.show();
}
@SuppressLint("ApplySharedPref") @SuppressLint("ApplySharedPref")
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
@ -495,8 +679,59 @@ public class MainActivity extends AppCompatActivity {
SharedPreferences.Editor editor = sharedpreferences.edit(); SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_INSTANCE, String.valueOf(data.getData())); editor.putString(Helper.PREF_INSTANCE, String.valueOf(data.getData()));
editor.commit(); editor.commit();
recreate(); finish();
} }
} }
} }
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NotNull
@Override
public Fragment getItem(final int position) {
if (Helper.isLoggedIn(MainActivity.this)) {
switch (position) {
case 0:
return overviewFragment;
case 1:
return subscriptionFragment;
case 2:
return trendingFragment;
case 3:
return recentFragment;
case 4:
return locaFragment;
}
} else {
switch (position) {
case 0:
return overviewFragment;
case 1:
return trendingFragment;
case 2:
return mostLikedFragment;
case 3:
return recentFragment;
case 4:
return locaFragment;
}
}
return null;
}
@Override
public int getCount() {
return 5;
}
}
public enum TypeOfConnection {
UNKNOWN,
NORMAL,
SURFING
}
} }

View File

@ -0,0 +1,130 @@
package app.fedilab.fedilabtube;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.InstanceData;
import app.fedilab.fedilabtube.databinding.ActivityManageInstancesBinding;
import app.fedilab.fedilabtube.drawer.AboutInstanceAdapter;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.sqlite.StoredInstanceDAO;
import app.fedilab.fedilabtube.viewmodel.InfoInstanceVM;
import static app.fedilab.fedilabtube.MainActivity.PICK_INSTANCE_SURF;
import static app.fedilab.fedilabtube.MainActivity.showRadioButtonDialogFullInstances;
public class ManageInstancesActivity extends AppCompatActivity implements AboutInstanceAdapter.AllInstancesRemoved {
private ActivityManageInstancesBinding binding;
private List<InstanceData.AboutInstance> aboutInstances;
private AboutInstanceAdapter aboutInstanceAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityManageInstancesBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
binding.loader.setVisibility(View.VISIBLE);
binding.noAction.setVisibility(View.GONE);
binding.lvInstances.setVisibility(View.GONE);
binding.actionButton.setOnClickListener(v -> showRadioButtonDialogFullInstances(ManageInstancesActivity.this, true));
aboutInstances = new ArrayList<>();
aboutInstanceAdapter = new AboutInstanceAdapter(this.aboutInstances);
aboutInstanceAdapter.allInstancesRemoved = this;
binding.lvInstances.setAdapter(aboutInstanceAdapter);
LinearLayoutManager layoutManager
= new LinearLayoutManager(ManageInstancesActivity.this);
binding.lvInstances.setLayoutManager(layoutManager);
InfoInstanceVM viewModelInfoInstance = new ViewModelProvider(ManageInstancesActivity.this).get(InfoInstanceVM.class);
viewModelInfoInstance.getInstances().observe(ManageInstancesActivity.this, this::manageVIewInfoInstance);
}
private void manageVIewInfoInstance(List<InstanceData.AboutInstance> aboutInstances) {
binding.loader.setVisibility(View.GONE);
if (aboutInstances == null || aboutInstances.size() == 0) {
binding.noAction.setVisibility(View.VISIBLE);
binding.lvInstances.setVisibility(View.GONE);
return;
}
binding.noAction.setVisibility(View.GONE);
binding.lvInstances.setVisibility(View.VISIBLE);
this.aboutInstances.addAll(aboutInstances);
aboutInstanceAdapter.notifyItemRangeInserted(0, aboutInstances.size());
}
@Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(R.anim.slide_out_up, R.anim.slide_in_up_down);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
overridePendingTransition(R.anim.slide_out_up, R.anim.slide_in_up_down);
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressLint("ApplySharedPref")
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_INSTANCE_SURF && resultCode == Activity.RESULT_OK) {
if (data != null && data.getData() != null) {
new Thread(() -> {
String newInstance = data.getData().toString().trim().toLowerCase();
InstanceData.AboutInstance aboutInstance = new RetrofitPeertubeAPI(ManageInstancesActivity.this, newInstance, null).getAboutInstance();
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new StoredInstanceDAO(ManageInstancesActivity.this, db).insertInstance(aboutInstance, newInstance);
runOnUiThread(() -> new Handler().post(() -> Helper.logoutNoRemoval(ManageInstancesActivity.this)));
}).start();
}
}
}
@Override
public void onAllInstancesRemoved() {
binding.noAction.setVisibility(View.VISIBLE);
binding.lvInstances.setVisibility(View.GONE);
}
}

View File

@ -0,0 +1,360 @@
package app.fedilab.fedilabtube;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.work.WorkManager;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import org.jetbrains.annotations.NotNull;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.NotificationSettings;
import app.fedilab.fedilabtube.client.entities.UserMe;
import app.fedilab.fedilabtube.client.entities.UserSettings;
import app.fedilab.fedilabtube.databinding.ActivityMyAccountSettingsBinding;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.worker.WorkHelper;
import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
import static app.fedilab.fedilabtube.worker.WorkHelper.NOTIFICATION_WORKER;
public class MyAccountActivity extends AppCompatActivity {
private static final int PICK_IMAGE = 466;
ActivityMyAccountSettingsBinding binding;
private Uri inputData;
private String fileName;
private NotificationSettings notificationSettings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMyAccountSettingsBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (MainActivity.userMe == null) {
finish();
return;
}
setTitle(String.format("@%s", MainActivity.userMe.getUsername()));
binding.displayname.setText(MainActivity.userMe.getAccount().getDisplayName());
binding.description.setText(MainActivity.userMe.getAccount().getDescription());
notificationSettings = MainActivity.userMe.getNotificationSettings();
initializeValues(notificationSettings.getAbuseStateChange(), binding.notifAbuseAcceptedApp, binding.notifAbuseAcceptedMail);
initializeValues(notificationSettings.getAbuseNewMessage(), binding.notifAbuseReceivedApp, binding.notifAbuseReceivedMail);
initializeValues(notificationSettings.getCommentMention(), binding.notifVideoMentionApp, binding.notifVideoMentionMail);
initializeValues(notificationSettings.getNewFollow(), binding.notifNewFollowersApp, binding.notifNewFollowersMail);
initializeValues(notificationSettings.getMyVideoImportFinished(), binding.notifVideoImportedApp, binding.notifVideoImportedMail);
initializeValues(notificationSettings.getMyVideoPublished(), binding.notifVideoPublishedApp, binding.notifVideoPublishedMail);
initializeValues(notificationSettings.getBlacklistOnMyVideo(), binding.notifBlockedApp, binding.notifBlockedMail);
initializeValues(notificationSettings.getNewCommentOnMyVideo(), binding.notifNewCommentApp, binding.notifNewCommentMail);
initializeValues(notificationSettings.getNewVideoFromSubscription(), binding.notifNewVideoApp, binding.notifNewVideoMail);
Helper.loadGiF(MyAccountActivity.this, MainActivity.userMe.getAccount().getAvatar() != null ? MainActivity.userMe.getAccount().getAvatar().getPath() : null, binding.profilePicture);
String[] refresh_array = getResources().getStringArray(R.array.refresh_time);
ArrayAdapter<String> refreshArray = new ArrayAdapter<>(MyAccountActivity.this,
android.R.layout.simple_spinner_dropdown_item, refresh_array);
binding.refreshTime.setAdapter(refreshArray);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int interval = sharedpreferences.getInt(Helper.NOTIFICATION_INTERVAL, 60);
binding.refreshTime.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
SharedPreferences.Editor editor = sharedpreferences.edit();
int time;
switch (position) {
case 1:
time = 15;
break;
case 2:
time = 30;
break;
case 3:
time = 60;
break;
case 4:
time = 120;
break;
case 5:
time = 360;
break;
case 6:
time = 720;
break;
default:
time = 0;
}
editor.putInt(Helper.NOTIFICATION_INTERVAL, time);
editor.apply();
WorkManager.getInstance(getApplicationContext()).cancelAllWorkByTag(NOTIFICATION_WORKER);
if (time > 0) {
WorkHelper.fetchNotifications(getApplication(), time);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
int position = 0;
switch (interval) {
case 0:
position = 0;
break;
case 15:
position = 1;
break;
case 30:
position = 2;
break;
case 60:
position = 3;
break;
case 120:
position = 4;
break;
case 360:
position = 5;
break;
case 720:
position = 6;
break;
}
binding.refreshTime.setSelection(position, false);
binding.selectFile.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(MyAccountActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MyAccountActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
return;
}
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
String[] mimetypes = {"image/*"};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, PICK_IMAGE);
});
}
@Override
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
getMenuInflater().inflate(R.menu.main_my_account, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_validate) {
item.setEnabled(false);
new Thread(() -> {
UserSettings userSettings = new UserSettings();
userSettings.setNotificationSettings(notificationSettings);
if (binding.displayname.getText() != null) {
userSettings.setDisplayName(binding.displayname.getText().toString().trim());
}
if (binding.description.getText() != null) {
userSettings.setDescription(binding.description.getText().toString().trim());
}
if (inputData != null) {
userSettings.setAvatarfile(inputData);
userSettings.setFileName(fileName);
}
try {
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(MyAccountActivity.this);
UserMe.AvatarResponse avatarResponse = api.updateUser(userSettings);
MainActivity.userMe.getAccount().setDisplayName(binding.displayname.getText().toString().trim());
MainActivity.userMe.getAccount().setDescription(binding.description.getText().toString().trim());
if (avatarResponse != null && avatarResponse.getAvatar() != null) {
MainActivity.userMe.getAccount().setAvatar(avatarResponse.getAvatar());
}
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
Toasty.info(MyAccountActivity.this, getString(R.string.account_updated), Toasty.LENGTH_LONG).show();
item.setEnabled(true);
};
mainHandler.post(myRunnable);
} catch (Exception | Error e) {
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
Toasty.error(MyAccountActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
item.setEnabled(true);
};
mainHandler.post(myRunnable);
}
}).start();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
if (data == null || data.getData() == null) {
Toasty.error(MyAccountActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return;
}
inputData = data.getData();
DocumentFile documentFile = DocumentFile.fromSingleUri(this, inputData);
if (documentFile != null) {
fileName = documentFile.getName();
}
Glide.with(MyAccountActivity.this)
.load(inputData)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(binding.profilePicture);
}
}
private void initializeValues(int value, SwitchCompat app, SwitchCompat email) {
switch (value) {
case 1:
app.setChecked(true);
email.setChecked(false);
break;
case 2:
app.setChecked(false);
email.setChecked(true);
break;
case 3:
app.setChecked(true);
email.setChecked(true);
break;
default:
app.setChecked(false);
email.setChecked(false);
}
app.setOnCheckedChangeListener((compoundButton, checked) -> {
int id = app.getId();
if (id == R.id.notif_new_video_app) {
notificationSettings.setNewVideoFromSubscription(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_new_comment_app) {
notificationSettings.setNewCommentOnMyVideo(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_blocked_app) {
notificationSettings.setBlacklistOnMyVideo(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_video_published_app) {
notificationSettings.setMyVideoPublished(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_video_imported_app) {
notificationSettings.setMyVideoImportFinished(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_new_followers_app) {
notificationSettings.setNewFollow(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_video_mention_app) {
notificationSettings.setCommentMention(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_abuse_received_app) {
notificationSettings.setAbuseNewMessage(getNewAppCheckedValue(checked, email));
} else if (id == R.id.notif_abuse_accepted_app) {
notificationSettings.setAbuseStateChange(getNewAppCheckedValue(checked, email));
}
});
email.setOnCheckedChangeListener((compoundButtonMail, checkedMail) -> {
int id = email.getId();
if (id == R.id.notif_new_video_mail) {
notificationSettings.setNewVideoFromSubscription(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_new_comment_mail) {
notificationSettings.setNewCommentOnMyVideo(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_blocked_mail) {
notificationSettings.setBlacklistOnMyVideo(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_video_published_mail) {
notificationSettings.setMyVideoPublished(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_video_imported_mail) {
notificationSettings.setMyVideoImportFinished(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_new_followers_mail) {
notificationSettings.setNewFollow(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_video_mention_mail) {
notificationSettings.setCommentMention(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_abuse_received_mail) {
notificationSettings.setAbuseNewMessage(getNewMailCheckedValue(checkedMail, app));
} else if (id == R.id.notif_abuse_accepted_mail) {
notificationSettings.setAbuseStateChange(getNewMailCheckedValue(checkedMail, app));
}
});
}
private int getNewAppCheckedValue(boolean checked, SwitchCompat email) {
int newValue;
if (checked && email.isChecked()) {
newValue = 3;
} else if (!checked && email.isChecked()) {
newValue = 2;
} else if (checked && !email.isChecked()) {
newValue = 1;
} else {
newValue = 0;
}
return newValue;
}
private int getNewMailCheckedValue(boolean checked, SwitchCompat app) {
int newValue;
if (checked && app.isChecked()) {
newValue = 3;
} else if (!checked && app.isChecked()) {
newValue = 1;
} else if (checked && !app.isChecked()) {
newValue = 2;
} else {
newValue = 0;
}
return newValue;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -16,21 +16,17 @@ package app.fedilab.fedilabtube;
import android.Manifest; import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -40,39 +36,34 @@ import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.ServerResponse;
import net.gotev.uploadservice.UploadInfo;
import net.gotev.uploadservice.UploadNotificationConfig;
import net.gotev.uploadservice.UploadStatusDelegate;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.ChannelData.Channel; import app.fedilab.fedilabtube.client.data.ChannelData.Channel;
import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.data.VideoData.Video; import app.fedilab.fedilabtube.client.data.VideoData.Video;
import app.fedilab.fedilabtube.client.entities.Item; import app.fedilab.fedilabtube.client.entities.Item;
import app.fedilab.fedilabtube.client.entities.ItemStr; import app.fedilab.fedilabtube.client.entities.ItemStr;
import app.fedilab.fedilabtube.client.entities.VideoParams; import app.fedilab.fedilabtube.client.entities.VideoParams;
import app.fedilab.fedilabtube.databinding.ActivityPeertubeEditBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
import app.fedilab.fedilabtube.viewmodel.MyVideoVM; import app.fedilab.fedilabtube.viewmodel.MyVideoVM;
import app.fedilab.fedilabtube.viewmodel.PostActionsVM; import app.fedilab.fedilabtube.viewmodel.PostActionsVM;
import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import mabbas007.tagsedittext.TagsEditText;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.PEERTUBEDELETEVIDEO; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.PEERTUBEDELETEVIDEO;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.MY_CHANNELS; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.MY_CHANNELS;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class PeertubeEditUploadActivity extends AppCompatActivity { public class PeertubeEditUploadActivity extends AppCompatActivity {
@ -82,23 +73,21 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724; private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
Item licenseToSend, privacyToSend, categoryToSend; Item licenseToSend, privacyToSend, categoryToSend;
ItemStr languageToSend; ItemStr languageToSend;
private Button set_upload_submit;
private Spinner set_upload_privacy, set_upload_categories, set_upload_licenses, set_upload_languages, set_upload_channel;
private EditText p_video_title, p_video_description;
private TagsEditText p_video_tags;
private CheckBox set_upload_nsfw, set_upload_enable_comments;
private LinkedHashMap<String, String> channels; private LinkedHashMap<String, String> channels;
private String videoId; private String videoId;
private Channel channel; private Channel channel;
private ImageView p_video_preview;
private Button set_preview;
private VideoParams videoParams; private VideoParams videoParams;
private Video video; private Video video;
private String channelToSendId; private String channelToSendId;
private ActivityPeertubeEditBinding binding;
private Uri inputData;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityPeertubeEditBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
@ -113,23 +102,8 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_peertube_edit);
set_upload_submit = findViewById(R.id.set_upload_submit);
Button set_upload_delete = findViewById(R.id.set_upload_delete);
set_upload_privacy = findViewById(R.id.set_upload_privacy);
set_upload_channel = findViewById(R.id.set_upload_channel);
set_upload_categories = findViewById(R.id.set_upload_categories);
set_upload_licenses = findViewById(R.id.set_upload_licenses);
set_upload_languages = findViewById(R.id.set_upload_languages);
p_video_title = findViewById(R.id.p_video_title);
p_video_description = findViewById(R.id.p_video_description);
p_video_tags = findViewById(R.id.p_video_tags);
p_video_preview = findViewById(R.id.p_video_preview);
set_upload_nsfw = findViewById(R.id.set_upload_nsfw);
set_upload_enable_comments = findViewById(R.id.set_upload_enable_comments);
set_preview = findViewById(R.id.set_preview);
set_upload_delete.setOnClickListener(v -> { binding.setUploadDelete.setOnClickListener(v -> {
AlertDialog.Builder builderInner; AlertDialog.Builder builderInner;
builderInner = new AlertDialog.Builder(PeertubeEditUploadActivity.this); builderInner = new AlertDialog.Builder(PeertubeEditUploadActivity.this);
builderInner.setMessage(getString(R.string.delete_video_confirmation)); builderInner.setMessage(getString(R.string.delete_video_confirmation));
@ -165,7 +139,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterCatgories = new ArrayAdapter<>(PeertubeEditUploadActivity.this, ArrayAdapter<String> adapterCatgories = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, categoriesA); android.R.layout.simple_spinner_dropdown_item, categoriesA);
set_upload_categories.setAdapter(adapterCatgories); binding.setUploadCategories.setAdapter(adapterCatgories);
//Populate licenses //Populate licenses
@ -183,7 +157,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterLicenses = new ArrayAdapter<>(PeertubeEditUploadActivity.this, ArrayAdapter<String> adapterLicenses = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, licensesA); android.R.layout.simple_spinner_dropdown_item, licensesA);
set_upload_licenses.setAdapter(adapterLicenses); binding.setUploadLicenses.setAdapter(adapterLicenses);
//Populate languages //Populate languages
@ -201,7 +175,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterLanguages = new ArrayAdapter<>(PeertubeEditUploadActivity.this, ArrayAdapter<String> adapterLanguages = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, languagesA); android.R.layout.simple_spinner_dropdown_item, languagesA);
set_upload_languages.setAdapter(adapterLanguages); binding.setUploadLanguages.setAdapter(adapterLanguages);
//Populate languages //Populate languages
@ -220,18 +194,19 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(PeertubeEditUploadActivity.this, ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, privaciesA); android.R.layout.simple_spinner_dropdown_item, privaciesA);
set_upload_privacy.setAdapter(adapterPrivacies); binding.setUploadPrivacy.setAdapter(adapterPrivacies);
TimelineVM feedsViewModel = new ViewModelProvider(PeertubeEditUploadActivity.this).get(TimelineVM.class); TimelineVM feedsViewModel = new ViewModelProvider(PeertubeEditUploadActivity.this).get(TimelineVM.class);
feedsViewModel.getMyVideo(null, videoId).observe(PeertubeEditUploadActivity.this, this::manageVIewVideo); feedsViewModel.getMyVideo(null, videoId).observe(PeertubeEditUploadActivity.this, this::manageVIewVideo);
channels = new LinkedHashMap<>(); channels = new LinkedHashMap<>();
setTitle(R.string.edit_video); setTitle(R.string.edit_video);
} }
public void manageUpdate(APIResponse apiResponse) { public void manageUpdate(APIResponse apiResponse) {
set_upload_submit.setEnabled(true); binding.setUploadSubmit.setEnabled(true);
if (apiResponse.getError() != null) { if (apiResponse.getError() != null) {
if (apiResponse.getError() != null && apiResponse.getError().getError() != null) if (apiResponse.getError() != null && apiResponse.getError().getError() != null)
Toasty.error(PeertubeEditUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(PeertubeEditUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
@ -247,7 +222,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
Toasty.error(PeertubeEditUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(PeertubeEditUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
else else
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
set_upload_submit.setEnabled(true); binding.setUploadSubmit.setEnabled(true);
return; return;
} }
@ -263,11 +238,11 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
categoryToSend = video.getCategory(); categoryToSend = video.getCategory();
if (video.getThumbnailPath() != null) { if (video.getThumbnailPath() != null) {
Helper.loadGiF(PeertubeEditUploadActivity.this, video.getThumbnailPath(), p_video_preview); Helper.loadGiF(PeertubeEditUploadActivity.this, video.getThumbnailPath(), binding.pVideoPreview);
} }
set_preview.setOnClickListener(v -> { binding.setPreview.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(PeertubeEditUploadActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != if (ContextCompat.checkSelfPermission(PeertubeEditUploadActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) { PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PeertubeEditUploadActivity.this, ActivityCompat.requestPermissions(PeertubeEditUploadActivity.this,
@ -324,11 +299,28 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
boolean commentEnabled = video.isCommentsEnabled(); boolean commentEnabled = video.isCommentsEnabled();
boolean isNSFW = video.isNsfw(); boolean isNSFW = video.isNsfw();
set_upload_enable_comments.setChecked(commentEnabled); binding.setUploadEnableComments.setChecked(commentEnabled);
set_upload_nsfw.setChecked(isNSFW); binding.setUploadNsfw.setChecked(isNSFW);
p_video_title.setText(title); binding.pVideoTitle.setText(title);
p_video_description.setText(video.getDescription()); binding.pVideoDescription.setText(video.getDescription());
new Thread(() -> {
try {
RetrofitPeertubeAPI api;
api = new RetrofitPeertubeAPI(PeertubeEditUploadActivity.this);
VideoData.Description description = api.getVideoDescription(video.getUuid());
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
if (description != null) {
binding.pVideoDescription.setText(description.getDescription());
}
};
mainHandler.post(myRunnable);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories()); LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories());
LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences()); LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences());
@ -382,7 +374,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
} }
//Manage privacies //Manage privacies
set_upload_privacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadPrivacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updatePrivacyPosition(position); updatePrivacyPosition(position);
@ -393,7 +385,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
}); });
set_upload_licenses.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadLicenses.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateLicensePosition(position); updateLicensePosition(position);
@ -405,7 +397,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
}); });
//Manage categories //Manage categories
set_upload_categories.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadCategories.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateCategoryPosition(position); updateCategoryPosition(position);
@ -418,7 +410,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
}); });
//Manage languages //Manage languages
set_upload_languages.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadLanguages.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateLanguagesPosition(position); updateLanguagesPosition(position);
@ -430,7 +422,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
}); });
//Manage languages //Manage languages
set_upload_channel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadChannel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -447,11 +439,11 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
Item finalLicenseToSend = licenseToSend; Item finalLicenseToSend = licenseToSend;
ItemStr finalLanguageToSend = languageToSend; ItemStr finalLanguageToSend = languageToSend;
Item finalPrivacyToSend = privacyToSend; Item finalPrivacyToSend = privacyToSend;
set_upload_submit.setOnClickListener(v -> { binding.setUploadSubmit.setOnClickListener(v -> {
String title1 = p_video_title.getText().toString().trim(); String title1 = binding.pVideoTitle.getText() != null ? binding.pVideoTitle.getText().toString().trim() : "";
String description = p_video_description.getText().toString().trim(); String description = binding.pVideoDescription.getText() != null ? binding.pVideoDescription.getText().toString().trim() : "";
boolean isNSFW1 = set_upload_nsfw.isChecked(); boolean isNSFW1 = binding.setUploadNsfw.isChecked();
boolean commentEnabled1 = set_upload_enable_comments.isChecked(); boolean commentEnabled1 = binding.setUploadEnableComments.isChecked();
videoParams = new VideoParams(); videoParams = new VideoParams();
videoParams.setName(title1); videoParams.setName(title1);
videoParams.setDescription(description); videoParams.setDescription(description);
@ -460,28 +452,27 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
videoParams.setCategory(finalCategoryToSend.getId()); videoParams.setCategory(finalCategoryToSend.getId());
videoParams.setLicence(String.valueOf(finalLicenseToSend.getId())); videoParams.setLicence(String.valueOf(finalLicenseToSend.getId()));
videoParams.setLanguage(finalLanguageToSend.getId()); videoParams.setLanguage(finalLanguageToSend.getId());
videoParams.setChannelId(channelToSendId); videoParams.setChannelId(channelToSendId);
videoParams.setPrivacy(finalPrivacyToSend.getId()); videoParams.setPrivacy(finalPrivacyToSend.getId());
List<String> tags = p_video_tags.getTags(); List<String> tags = binding.pVideoTags.getTags();
videoParams.setTags(tags); videoParams.setTags(tags);
set_upload_submit.setEnabled(false); binding.setUploadSubmit.setEnabled(false);
MyVideoVM myVideoVM = new ViewModelProvider(PeertubeEditUploadActivity.this).get(MyVideoVM.class); MyVideoVM myVideoVM = new ViewModelProvider(PeertubeEditUploadActivity.this).get(MyVideoVM.class);
myVideoVM.updateVideo(videoId, videoParams, null, null).observe(PeertubeEditUploadActivity.this, this::manageUpdate); myVideoVM.updateVideo(videoId, videoParams, inputData, inputData).observe(PeertubeEditUploadActivity.this, this::manageUpdate);
}); });
set_upload_privacy.setSelection(privacyPosition, false); binding.setUploadPrivacy.setSelection(privacyPosition, false);
updatePrivacyPosition(privacyPosition); updatePrivacyPosition(privacyPosition);
set_upload_languages.setSelection(languagePosition, false); binding.setUploadLanguages.setSelection(languagePosition, false);
updateLanguagesPosition(languagePosition); updateLanguagesPosition(languagePosition);
set_upload_licenses.setSelection(licensePosition, false); binding.setUploadLicenses.setSelection(licensePosition, false);
updateLicensePosition(licensePosition); updateLicensePosition(licensePosition);
set_upload_categories.setSelection(categoryPosition, false); binding.setUploadCategories.setSelection(categoryPosition, false);
updateCategoryPosition(categoryPosition); updateCategoryPosition(categoryPosition);
List<String> tags = video.getTags(); List<String> tags = video.getTags();
if (tags != null && tags.size() > 0) { if (tags != null && tags.size() > 0) {
p_video_tags.setTags(tags.toArray(new String[0])); binding.pVideoTags.setTags(tags.toArray(new String[0]));
} }
} }
@ -572,53 +563,12 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show(); Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return; return;
} }
UploadNotificationConfig uploadConfig = new UploadNotificationConfig(); inputData = data.getData();
uploadConfig.getCompleted().autoClear = true; Glide.with(PeertubeEditUploadActivity.this)
try { .load(data.getData())
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); .thumbnail(0.1f)
String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); .apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
Uri uri = data.getData(); .into(binding.pVideoPreview);
try {
String uploadId = UUID.randomUUID().toString();
new MultipartUploadRequest(PeertubeEditUploadActivity.this, uploadId, "https://" + Helper.getLiveInstance(PeertubeEditUploadActivity.this) + "/api/v1/" + String.format("/videos/%s", video.getId()))
.addFileToUpload(uri.toString().replace("file://", ""), "thumbnailfile")
.setMethod("PUT")
.addHeader("Authorization", "Bearer " + token)
.setNotificationConfig(uploadConfig)
.setMaxRetries(2)
.setDelegate(new UploadStatusDelegate() {
@Override
public void onProgress(Context context, UploadInfo uploadInfo) {
// your code here
}
@Override
public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
Exception exception) {
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
@Override
public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
Glide.with(PeertubeEditUploadActivity.this)
.load(uri)
.into(p_video_preview);
}
@Override
public void onCancelled(Context context, UploadInfo uploadInfo) {
// your code here
}
})
.startUpload();
} catch (FileNotFoundException e) {
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
} catch (MalformedURLException e) {
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
} }
} }
@ -651,7 +601,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(PeertubeEditUploadActivity.this, ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, channelName); android.R.layout.simple_spinner_dropdown_item, channelName);
set_upload_channel.setAdapter(adapterChannel); binding.setUploadChannel.setAdapter(adapterChannel);
int channelPosition = 0; int channelPosition = 0;
if (channels.containsKey(channel.getName())) { if (channels.containsKey(channel.getName())) {
LinkedHashMap<String, String> channelsIterator = new LinkedHashMap<>(channels); LinkedHashMap<String, String> channelsIterator = new LinkedHashMap<>(channels);
@ -666,9 +616,15 @@ public class PeertubeEditUploadActivity extends AppCompatActivity {
channelPosition++; channelPosition++;
} }
} }
set_upload_channel.setSelection(channelPosition, false); binding.setUploadChannel.setSelection(channelPosition, false);
updateUploadChannel(channelPosition); updateUploadChannel(channelPosition);
set_upload_submit.setEnabled(true); binding.setUploadSubmit.setEnabled(true);
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
} }
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})

View File

@ -25,17 +25,11 @@ import android.text.method.LinkMovementMethod;
import android.util.Patterns; import android.util.Patterns;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import java.util.Arrays; import java.util.Arrays;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -43,6 +37,7 @@ import java.util.regex.Pattern;
import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.entities.AccountCreation; import app.fedilab.fedilabtube.client.entities.AccountCreation;
import app.fedilab.fedilabtube.databinding.ActivityRegisterPeertubeBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@ -51,100 +46,88 @@ import static app.fedilab.fedilabtube.MainActivity.PICK_INSTANCE;
public class PeertubeRegisterActivity extends AppCompatActivity { public class PeertubeRegisterActivity extends AppCompatActivity {
private Button signup;
private TextView error_message;
private String instance; private String instance;
private TextInputEditText login_instance; private ActivityRegisterPeertubeBinding binding;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_peertube); binding = ActivityRegisterPeertubeBinding.inflate(getLayoutInflater());
View mainView = binding.getRoot();
setContentView(mainView);
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
signup = findViewById(R.id.signup);
TextInputLayout login_instance_container = findViewById(R.id.login_instance_container);
LinearLayout title_login_instance = findViewById(R.id.title_login_instance);
TextInputEditText username = findViewById(R.id.username);
TextInputEditText email = findViewById(R.id.email);
TextInputEditText password = findViewById(R.id.password);
TextInputEditText password_confirm = findViewById(R.id.password_confirm);
login_instance = findViewById(R.id.login_instance);
CheckBox agreement = findViewById(R.id.agreement);
error_message = findViewById(R.id.error_message);
if (BuildConfig.full_instances) { if (BuildConfig.full_instances) {
login_instance_container.setVisibility(View.VISIBLE); binding.loginInstanceContainer.setVisibility(View.VISIBLE);
title_login_instance.setVisibility(View.VISIBLE); binding.titleLoginInstance.setVisibility(View.VISIBLE);
} else { } else {
login_instance_container.setVisibility(View.GONE); binding.loginInstanceContainer.setVisibility(View.GONE);
title_login_instance.setVisibility(View.GONE); binding.titleLoginInstance.setVisibility(View.GONE);
} }
username.setOnFocusChangeListener((view, focused) -> { binding.username.setOnFocusChangeListener((view, focused) -> {
if (!focused && username.getText() != null) { if (!focused && binding.username.getText() != null) {
Pattern patternUsername = Pattern.compile("^[a-z0-9._]{1,50}$"); Pattern patternUsername = Pattern.compile("^[a-z0-9._]{1,50}$");
Matcher matcherMaxId = patternUsername.matcher(username.getText().toString()); Matcher matcherMaxId = patternUsername.matcher(binding.username.getText().toString());
if (!matcherMaxId.matches()) { if (!matcherMaxId.matches()) {
username.setError(getString(R.string.username_error)); binding.username.setError(getString(R.string.username_error));
} }
} }
}); });
Button instance_help = findViewById(R.id.instance_help);
instance_help.setOnClickListener(v -> { binding.instanceHelp.setOnClickListener(v -> {
Intent intent = new Intent(PeertubeRegisterActivity.this, InstancePickerActivity.class); Intent intent = new Intent(PeertubeRegisterActivity.this, InstancePickerActivity.class);
startActivityForResult(intent, PICK_INSTANCE); startActivityForResult(intent, PICK_INSTANCE);
}); });
email.setOnFocusChangeListener((view, focused) -> { binding.email.setOnFocusChangeListener((view, focused) -> {
if (!focused && email.getText() != null) { if (!focused && binding.email.getText() != null) {
Pattern patternUsername = Patterns.EMAIL_ADDRESS; Pattern patternUsername = Patterns.EMAIL_ADDRESS;
Matcher matcherMaxId = patternUsername.matcher(email.getText().toString()); Matcher matcherMaxId = patternUsername.matcher(binding.email.getText().toString());
if (!matcherMaxId.matches()) { if (!matcherMaxId.matches()) {
email.setError(getString(R.string.email_error)); binding.email.setError(getString(R.string.email_error));
} }
} }
}); });
password.setOnFocusChangeListener((view, focused) -> { binding.password.setOnFocusChangeListener((view, focused) -> {
if (!focused && password.getText() != null) { if (!focused && binding.password.getText() != null) {
if (password.getText().length() < 6) { if (binding.password.getText().length() < 6) {
password.setError(getString(R.string.password_length_error)); binding.password.setError(getString(R.string.password_length_error));
} }
} }
}); });
password_confirm.setOnFocusChangeListener((view, focused) -> { binding.passwordConfirm.setOnFocusChangeListener((view, focused) -> {
if (!focused && password_confirm.getText() != null && password.getText() != null) { if (!focused && binding.passwordConfirm.getText() != null && binding.password.getText() != null) {
if (password_confirm.getText().toString().compareTo(password.getText().toString()) != 0) { if (binding.passwordConfirm.getText().toString().compareTo(binding.password.getText().toString()) != 0) {
password_confirm.setError(getString(R.string.password)); binding.passwordConfirm.setError(getString(R.string.password));
} }
} }
}); });
setTextAgreement(); setTextAgreement();
signup.setOnClickListener(view -> { binding.signup.setOnClickListener(view -> {
error_message.setVisibility(View.GONE); binding.errorMessage.setVisibility(View.GONE);
if (username.getText() == null || email.getText() == null || password.getText() == null || password_confirm.getText() == null || username.getText().toString().trim().length() == 0 || email.getText().toString().trim().length() == 0 || if (binding.username.getText() == null || binding.email.getText() == null || binding.password.getText() == null || binding.passwordConfirm.getText() == null || binding.username.getText().toString().trim().length() == 0 || binding.email.getText().toString().trim().length() == 0 ||
password.getText().toString().trim().length() == 0 || password_confirm.getText().toString().trim().length() == 0 || !agreement.isChecked()) { binding.password.getText().toString().trim().length() == 0 || binding.passwordConfirm.getText().toString().trim().length() == 0 || !binding.agreement.isChecked()) {
Toasty.error(PeertubeRegisterActivity.this, getString(R.string.all_field_filled)).show(); Toasty.error(PeertubeRegisterActivity.this, getString(R.string.all_field_filled)).show();
return; return;
} }
if (!password.getText().toString().trim().equals(password_confirm.getText().toString().trim())) { if (!binding.password.getText().toString().trim().equals(binding.passwordConfirm.getText().toString().trim())) {
Toasty.error(PeertubeRegisterActivity.this, getString(R.string.password_error)).show(); Toasty.error(PeertubeRegisterActivity.this, getString(R.string.password_error)).show();
return; return;
} }
if (!android.util.Patterns.EMAIL_ADDRESS.matcher(email.getText().toString().trim()).matches()) { if (!android.util.Patterns.EMAIL_ADDRESS.matcher(binding.email.getText().toString().trim()).matches()) {
Toasty.error(PeertubeRegisterActivity.this, getString(R.string.email_error)).show(); Toasty.error(PeertubeRegisterActivity.this, getString(R.string.email_error)).show();
return; return;
} }
String[] emailArray = email.getText().toString().split("@"); String[] emailArray = binding.email.getText().toString().split("@");
if (!BuildConfig.full_instances) { if (!BuildConfig.full_instances) {
if (emailArray.length > 1 && !Arrays.asList(Helper.valideEmails).contains(emailArray[1])) { if (emailArray.length > 1 && !Arrays.asList(Helper.valideEmails).contains(emailArray[1])) {
Toasty.error(PeertubeRegisterActivity.this, getString(R.string.email_error_domain, emailArray[1])).show(); Toasty.error(PeertubeRegisterActivity.this, getString(R.string.email_error_domain, emailArray[1])).show();
@ -152,23 +135,23 @@ public class PeertubeRegisterActivity extends AppCompatActivity {
} }
} }
if (password.getText().toString().trim().length() < 8) { if (binding.password.getText().toString().trim().length() < 8) {
Toasty.error(PeertubeRegisterActivity.this, getString(R.string.password_too_short)).show(); Toasty.error(PeertubeRegisterActivity.this, getString(R.string.password_too_short)).show();
return; return;
} }
if (username.getText().toString().matches("[a-z0-9_]")) { if (binding.username.getText().toString().matches("[a-z0-9_]")) {
Toasty.error(PeertubeRegisterActivity.this, getString(R.string.username_error)).show(); Toasty.error(PeertubeRegisterActivity.this, getString(R.string.username_error)).show();
return; return;
} }
signup.setEnabled(false); binding.signup.setEnabled(false);
if (BuildConfig.full_instances) { if (BuildConfig.full_instances) {
if (login_instance.getText() != null) { if (binding.loginInstance.getText() != null) {
instance = login_instance.getText().toString(); instance = binding.loginInstance.getText().toString();
} else { } else {
instance = ""; instance = "";
} }
login_instance.setOnFocusChangeListener((view1, focus) -> { binding.loginInstance.setOnFocusChangeListener((view1, focus) -> {
if (!focus) { if (!focus) {
setTextAgreement(); setTextAgreement();
} }
@ -182,10 +165,10 @@ public class PeertubeRegisterActivity extends AppCompatActivity {
} }
AccountCreation accountCreation = new AccountCreation(); AccountCreation accountCreation = new AccountCreation();
accountCreation.setEmail(email.getText().toString().trim()); accountCreation.setEmail(binding.email.getText().toString().trim());
accountCreation.setPassword(password.getText().toString().trim()); accountCreation.setPassword(binding.password.getText().toString().trim());
accountCreation.setPasswordConfirm(password_confirm.getText().toString().trim()); accountCreation.setPasswordConfirm(binding.passwordConfirm.getText().toString().trim());
accountCreation.setUsername(username.getText().toString().trim()); accountCreation.setUsername(binding.username.getText().toString().trim());
accountCreation.setInstance(instance); accountCreation.setInstance(instance);
new Thread(() -> { new Thread(() -> {
@ -210,9 +193,9 @@ public class PeertubeRegisterActivity extends AppCompatActivity {
} else { } else {
errorMessage = getString(R.string.toast_error); errorMessage = getString(R.string.toast_error);
} }
error_message.setText(errorMessage); binding.errorMessage.setText(errorMessage);
error_message.setVisibility(View.VISIBLE); binding.errorMessage.setVisibility(View.VISIBLE);
signup.setEnabled(true); binding.signup.setEnabled(true);
return; return;
} }
@ -260,8 +243,8 @@ public class PeertubeRegisterActivity extends AppCompatActivity {
if (requestCode == PICK_INSTANCE && resultCode == Activity.RESULT_OK) { if (requestCode == PICK_INSTANCE && resultCode == Activity.RESULT_OK) {
if (data != null && data.getData() != null) { if (data != null && data.getData() != null) {
String instance = String.valueOf(data.getData()); String instance = String.valueOf(data.getData());
login_instance.setText(instance); binding.loginInstance.setText(instance);
login_instance.setSelection(instance.length()); binding.loginInstance.setSelection(instance.length());
setTextAgreement(); setTextAgreement();
} }
} }
@ -275,9 +258,9 @@ public class PeertubeRegisterActivity extends AppCompatActivity {
agreement_text.setMovementMethod(null); agreement_text.setMovementMethod(null);
agreement_text.setText(null); agreement_text.setText(null);
if (BuildConfig.full_instances) { if (BuildConfig.full_instances) {
if (login_instance.getText() != null) { if (binding.loginInstance.getText() != null) {
content_agreement = getString(R.string.agreement_check_peertube, content_agreement = getString(R.string.agreement_check_peertube,
"<a href='https://" + login_instance.getText().toString() + "/about/instance#terms-section' >" + tos + "</a>" "<a href='https://" + binding.loginInstance.getText().toString() + "/about/instance#terms-section' >" + tos + "</a>"
); );
} }
} else { } else {

View File

@ -21,63 +21,63 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.Cursor; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.OpenableColumns;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.UploadNotificationAction;
import net.gotev.uploadservice.UploadNotificationConfig;
import java.io.File; import net.gotev.uploadservice.data.UploadNotificationAction;
import net.gotev.uploadservice.data.UploadNotificationConfig;
import net.gotev.uploadservice.data.UploadNotificationStatusConfig;
import net.gotev.uploadservice.extensions.ContextExtensionsKt;
import net.gotev.uploadservice.protocols.multipart.MultipartUploadRequest;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.ChannelData; import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.client.entities.UserMe;
import app.fedilab.fedilabtube.databinding.ActivityPeertubeUploadBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation; import static app.fedilab.fedilabtube.MainActivity.userMe;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.MY_CHANNELS; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.MY_CHANNELS;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class PeertubeUploadActivity extends AppCompatActivity { public class PeertubeUploadActivity extends AppCompatActivity {
public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
private final int PICK_IVDEO = 52378; private final int PICK_IVDEO = 52378;
private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
private Button set_upload_file, set_upload_submit;
private Spinner set_upload_privacy, set_upload_channel;
private TextView set_upload_file_name;
private EditText video_title;
private HashMap<String, String> channels; private HashMap<String, String> channels;
private Uri uri; private Uri uri;
private String filename; private String filename;
private HashMap<Integer, String> privacyToSend; private HashMap<Integer, String> privacyToSend;
private HashMap<String, String> channelToSend; private HashMap<String, String> channelToSend;
private ActivityPeertubeUploadBinding binding;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -86,14 +86,60 @@ public class PeertubeUploadActivity extends AppCompatActivity {
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_peertube_upload); binding = ActivityPeertubeUploadBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
new Thread(() -> {
UserMe.VideoQuota videoQuotaReply = new RetrofitPeertubeAPI(PeertubeUploadActivity.this).getVideoQuota();
runOnUiThread(() -> {
if (videoQuotaReply != null) {
long videoQuota = videoQuotaReply.getVideoQuotaUsed();
long dailyQuota = videoQuotaReply.getVideoQuotaUsedDaily();
long instanceVideoQuota = userMe.getVideoQuota();
long instanceDailyQuota = userMe.getVideoQuotaDaily();
if (instanceVideoQuota != -1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
binding.totalQuota.setProgress((int) (videoQuota * 100 / instanceVideoQuota), true);
} else {
binding.totalQuota.setProgress((int) (videoQuota * 100 / instanceVideoQuota));
}
} else {
int progress = videoQuota > 0 ? 30 : 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
binding.totalQuota.setProgress(progress, true);
} else {
binding.totalQuota.setProgress(progress);
}
}
if (instanceDailyQuota != -1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
binding.dailyQuota.setProgress((int) (dailyQuota * 100 / instanceDailyQuota), true);
} else {
binding.dailyQuota.setProgress((int) (dailyQuota * 100 / instanceDailyQuota));
}
} else {
int progress = dailyQuota > 0 ? 30 : 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
binding.dailyQuota.setProgress(progress, true);
} else {
binding.dailyQuota.setProgress(progress);
}
}
binding.totalQuotaValue.setText(
String.format(Locale.getDefault(), "%s/%s",
Helper.returnRoundedSize(PeertubeUploadActivity.this, videoQuota),
Helper.returnRoundedSize(PeertubeUploadActivity.this, instanceVideoQuota)));
binding.dailyQuotaValue.setText(
String.format(Locale.getDefault(), "%s/%s",
Helper.returnRoundedSize(PeertubeUploadActivity.this, dailyQuota),
Helper.returnRoundedSize(PeertubeUploadActivity.this, instanceDailyQuota)));
}
});
}).start();
set_upload_file = findViewById(R.id.set_upload_file);
set_upload_file_name = findViewById(R.id.set_upload_file_name);
set_upload_channel = findViewById(R.id.set_upload_channel);
set_upload_privacy = findViewById(R.id.set_upload_privacy);
set_upload_submit = findViewById(R.id.set_upload_submit);
video_title = findViewById(R.id.video_title);
ChannelsVM viewModelC = new ViewModelProvider(PeertubeUploadActivity.this).get(ChannelsVM.class); ChannelsVM viewModelC = new ViewModelProvider(PeertubeUploadActivity.this).get(ChannelsVM.class);
viewModelC.get(MY_CHANNELS, null).observe(PeertubeUploadActivity.this, this::manageVIewChannels); viewModelC.get(MY_CHANNELS, null).observe(PeertubeUploadActivity.this, this::manageVIewChannels);
@ -109,33 +155,18 @@ public class PeertubeUploadActivity extends AppCompatActivity {
Toasty.error(PeertubeUploadActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show(); Toasty.error(PeertubeUploadActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return; return;
} }
set_upload_submit.setEnabled(true); binding.setUploadSubmit.setEnabled(true);
uri = data.getData(); uri = data.getData();
String uriString = uri.toString();
File myFile = new File(uriString);
filename = null; filename = null;
if (uriString.startsWith("content://")) { DocumentFile documentFile = DocumentFile.fromSingleUri(this, uri);
Cursor cursor = null; if (documentFile != null) {
try { filename = documentFile.getName();
cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
assert cursor != null;
cursor.close();
}
} else if (uriString.startsWith("file://")) {
filename = myFile.getName();
} }
if (filename == null) { if (filename == null) {
filename = new Date().toString(); filename = new Date().toString();
} }
set_upload_file_name.setVisibility(View.VISIBLE); binding.setUploadFileName.setVisibility(View.VISIBLE);
set_upload_file_name.setText(filename); binding.setUploadFileName.setText(filename);
} }
} }
@ -179,7 +210,7 @@ public class PeertubeUploadActivity extends AppCompatActivity {
channelToSend.put(channelName[0], channelId[0]); channelToSend.put(channelName[0], channelId[0]);
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(PeertubeUploadActivity.this, ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(PeertubeUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, channelName); android.R.layout.simple_spinner_dropdown_item, channelName);
set_upload_channel.setAdapter(adapterChannel); binding.setUploadChannel.setAdapter(adapterChannel);
if (peertubeInformation == null) { if (peertubeInformation == null) {
return; return;
@ -209,10 +240,10 @@ public class PeertubeUploadActivity extends AppCompatActivity {
ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(PeertubeUploadActivity.this, ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(PeertubeUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, privaciesA); android.R.layout.simple_spinner_dropdown_item, privaciesA);
set_upload_privacy.setAdapter(adapterPrivacies); binding.setUploadPrivacy.setAdapter(adapterPrivacies);
//Manage privacies //Manage privacies
set_upload_privacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadPrivacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies()); LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
@ -235,9 +266,9 @@ public class PeertubeUploadActivity extends AppCompatActivity {
} }
}); });
set_upload_file.setEnabled(true); binding.setUploadFile.setEnabled(true);
set_upload_file.setOnClickListener(v -> { binding.setUploadFile.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(PeertubeUploadActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != if (ContextCompat.checkSelfPermission(PeertubeUploadActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) { PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PeertubeUploadActivity.this, ActivityCompat.requestPermissions(PeertubeUploadActivity.this,
@ -245,7 +276,7 @@ public class PeertubeUploadActivity extends AppCompatActivity {
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
return; return;
} }
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); intent.setType("*/*");
String[] mimetypes = {"video/*"}; String[] mimetypes = {"video/*"};
@ -255,7 +286,7 @@ public class PeertubeUploadActivity extends AppCompatActivity {
}); });
//Manage languages //Manage languages
set_upload_channel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.setUploadChannel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels); LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels);
@ -279,44 +310,33 @@ public class PeertubeUploadActivity extends AppCompatActivity {
} }
}); });
set_upload_submit.setOnClickListener(v -> { binding.setUploadSubmit.setOnClickListener(v -> {
if (uri != null) { if (uri != null) {
Map.Entry<String, String> channelM = channelToSend.entrySet().iterator().next(); Map.Entry<String, String> channelM = channelToSend.entrySet().iterator().next();
String idChannel = channelM.getValue(); String idChannel = channelM.getValue();
Map.Entry<Integer, String> privacyM = privacyToSend.entrySet().iterator().next(); Map.Entry<Integer, String> privacyM = privacyToSend.entrySet().iterator().next();
Integer idPrivacy = privacyM.getKey(); Integer idPrivacy = privacyM.getKey();
if (binding.videoTitle.getText() != null && binding.videoTitle.getText().toString().trim().length() > 0) {
filename = binding.videoTitle.getText().toString().trim();
}
try { try {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
UploadNotificationConfig uploadConfig = new UploadNotificationConfig();
Intent in = new Intent(PeertubeUploadActivity.this, PeertubeEditUploadActivity.class);
PendingIntent clickIntent = PendingIntent.getActivity(PeertubeUploadActivity.this, 1, in, PendingIntent.FLAG_UPDATE_CURRENT);
uploadConfig
.setClearOnActionForAllStatuses(true);
new MultipartUploadRequest(PeertubeUploadActivity.this, "https://" + Helper.getLiveInstance(PeertubeUploadActivity.this) + "/api/v1/videos/upload")
uploadConfig.getProgress().message = getString(R.string.uploading); .setMethod("POST")
uploadConfig.getCompleted().message = getString(R.string.upload_video_success); .setBearerAuth(token)
uploadConfig.getError().message = getString(R.string.toast_error); .addHeader("User-Agent", getString(R.string.app_name) + "/" + BuildConfig.VERSION_NAME)
uploadConfig.getCancelled().message = getString(R.string.toast_cancelled);
uploadConfig.getCompleted().actions.add(new UploadNotificationAction(R.drawable.ic_baseline_check_24, getString(R.string.video_uploaded_action), clickIntent));
if (video_title != null && video_title.getText() != null && video_title.getText().toString().trim().length() > 0) {
filename = video_title.getText().toString().trim();
}
String uploadId = UUID.randomUUID().toString();
new MultipartUploadRequest(PeertubeUploadActivity.this, uploadId, "https://" + Helper.getLiveInstance(PeertubeUploadActivity.this) + "/api/v1/videos/upload")
.addFileToUpload(uri.toString().replace("file://", ""), "videofile")
.addHeader("Authorization", "Bearer " + token)
.setNotificationConfig(uploadConfig)
.addParameter("name", filename)
.addParameter("channelId", idChannel)
.addParameter("privacy", String.valueOf(idPrivacy)) .addParameter("privacy", String.valueOf(idPrivacy))
.addParameter("nsfw", "false") .addParameter("nsfw", "false")
.addParameter("name", filename)
.addParameter("commentsEnabled", "true") .addParameter("commentsEnabled", "true")
.addParameter("downloadEnabled", "true")
.addParameter("waitTranscoding", "true") .addParameter("waitTranscoding", "true")
.setMaxRetries(3) .addParameter("channelId", idChannel)
.addFileToUpload(uri.toString(), "videofile")
.setNotificationConfig((context, uploadId) -> getNotificationConfig(uploadId))
.setMaxRetries(2)
.startUpload(); .startUpload();
finish(); finish();
} catch (Exception exc) { } catch (Exception exc) {
@ -325,4 +345,74 @@ public class PeertubeUploadActivity extends AppCompatActivity {
} }
}); });
} }
UploadNotificationConfig getNotificationConfig(String uploadId) {
PendingIntent clickIntent = PendingIntent.getActivity(
PeertubeUploadActivity.this, 1, new Intent(this, PeertubeEditUploadActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
final boolean autoClear = false;
final boolean clearOnAction = true;
final boolean ringToneEnabled = true;
final ArrayList<UploadNotificationAction> noActions = new ArrayList<>(1);
final UploadNotificationAction cancelAction = new UploadNotificationAction(
R.drawable.ic_baseline_cancel_24,
getString(R.string.cancel),
ContextExtensionsKt.getCancelUploadIntent(this, uploadId)
);
final ArrayList<UploadNotificationAction> progressActions = new ArrayList<>(1);
progressActions.add(cancelAction);
UploadNotificationStatusConfig progress = new UploadNotificationStatusConfig(
getString(R.string.app_name),
getString(R.string.uploading),
R.drawable.ic_baseline_cloud_upload_24,
Color.BLUE,
null,
clickIntent,
progressActions,
clearOnAction,
autoClear
);
UploadNotificationStatusConfig success = new UploadNotificationStatusConfig(
getString(R.string.app_name),
getString(R.string.upload_video_success),
R.drawable.ic_baseline_check_24,
Color.GREEN,
null,
clickIntent,
noActions,
clearOnAction,
autoClear
);
UploadNotificationStatusConfig error = new UploadNotificationStatusConfig(
getString(R.string.app_name),
getString(R.string.toast_error),
R.drawable.ic_baseline_error_24,
Color.RED,
null,
clickIntent,
noActions,
clearOnAction,
autoClear
);
UploadNotificationStatusConfig cancelled = new UploadNotificationStatusConfig(
getString(R.string.app_name),
getString(R.string.toast_cancelled),
R.drawable.ic_baseline_cancel_24,
Color.YELLOW,
null,
clickIntent,
noActions,
clearOnAction
);
return new UploadNotificationConfig(FedilabTube.UPLOAD_CHANNEL_ID, ringToneEnabled, progress, success, error, cancelled);
}
} }

View File

@ -14,6 +14,7 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
@ -24,12 +25,14 @@ import androidx.fragment.app.FragmentTransaction;
import app.fedilab.fedilabtube.client.data.PlaylistData; import app.fedilab.fedilabtube.client.data.PlaylistData;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
public class PlaylistsActivity extends AppCompatActivity { public class PlaylistsActivity extends AppCompatActivity {
private final int PICK_IMPORT = 5556;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -58,7 +61,7 @@ public class PlaylistsActivity extends AppCompatActivity {
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment(); DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.VIDEOS_IN_PLAYLIST); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.VIDEOS_IN_PLAYLIST);
bundle.putSerializable("playlistId", playlist.getId()); bundle.putSerializable("playlistId", playlist.getUuid());
displayVideosFragment.setArguments(bundle); displayVideosFragment.setArguments(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.nav_host_fragment, displayVideosFragment).commit(); ft.add(R.id.nav_host_fragment, displayVideosFragment).commit();
@ -66,6 +69,22 @@ public class PlaylistsActivity extends AppCompatActivity {
} }
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMPORT && resultCode == RESULT_OK) {
if (data == null || data.getData() == null) {
Toasty.error(PlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
return;
}
PlaylistExportHelper.manageIntentUrl(PlaylistsActivity.this, data);
} else if (requestCode == PICK_IMPORT) {
Toasty.error(PlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {

View File

@ -16,11 +16,22 @@ package app.fedilab.fedilabtube;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull;
import app.fedilab.fedilabtube.databinding.ActivitySearchResultBinding;
import app.fedilab.fedilabtube.fragment.DisplayChannelsFragment;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@ -29,12 +40,15 @@ public class SearchActivity extends AppCompatActivity {
private String search; private String search;
private ActivitySearchResultBinding binding;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivitySearchResultBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
setContentView(R.layout.activity_search_result);
Bundle b = getIntent().getExtras(); Bundle b = getIntent().getExtras();
if (b != null) { if (b != null) {
search = b.getString("search"); search = b.getString("search");
@ -46,15 +60,64 @@ public class SearchActivity extends AppCompatActivity {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(search); setTitle(search);
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.videos)));
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.channels)));
binding.searchPager.setOffscreenPageLimit(2);
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
binding.searchPager.setAdapter(mPagerAdapter);
binding.searchPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
TabLayout.Tab tab = binding.searchTabLayout.getTabAt(position);
if (tab != null)
tab.select();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
binding.searchTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
binding.searchPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
Fragment fragment = null;
if (binding.searchPager.getAdapter() != null)
fragment = (Fragment) binding.searchPager.getAdapter().instantiateItem(binding.searchPager, tab.getPosition());
switch (tab.getPosition()) {
case 0:
if (fragment != null) {
DisplayVideosFragment displayVideosFragment = ((DisplayVideosFragment) fragment);
displayVideosFragment.scrollToTop();
}
break;
case 1:
if (fragment != null) {
DisplayChannelsFragment displayChannelsFragment = ((DisplayChannelsFragment) fragment);
displayChannelsFragment.scrollToTop();
}
break;
}
}
});
if (savedInstanceState == null) {
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle();
bundle.putString("search_peertube", search);
displayVideosFragment.setArguments(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, displayVideosFragment).commit();
}
} }
@ -67,4 +130,37 @@ public class SearchActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
/**
* Pager adapter for the 2 fragments
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NotNull
@Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
if (position == 0) {
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
bundle.putString("search_peertube", search);
displayVideosFragment.setArguments(bundle);
return displayVideosFragment;
}
DisplayChannelsFragment displayChannelsFragment = new DisplayChannelsFragment();
bundle.putString("search_peertube", search);
displayChannelsFragment.setArguments(bundle);
return displayChannelsFragment;
}
@Override
public int getCount() {
return 2;
}
}
} }

View File

@ -21,12 +21,8 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.RadioGroup;
import android.widget.Spinner;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
@ -42,27 +38,29 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import app.fedilab.fedilabtube.client.entities.SepiaSearch; import app.fedilab.fedilabtube.client.entities.SepiaSearch;
import app.fedilab.fedilabtube.databinding.ActivitySepiaSearchBinding;
import app.fedilab.fedilabtube.fragment.DisplaySepiaSearchFragment; import app.fedilab.fedilabtube.fragment.DisplaySepiaSearchFragment;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import mabbas007.tagsedittext.TagsEditText;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation;
import static app.fedilab.fedilabtube.PeertubeActivity.hideKeyboard; import static app.fedilab.fedilabtube.PeertubeActivity.hideKeyboard;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class SepiaSearchActivity extends AppCompatActivity { public class SepiaSearchActivity extends AppCompatActivity {
private SepiaSearch sepiaSearchVideo, sepiaSearchChannel; private SepiaSearch sepiaSearchVideo, sepiaSearchChannel;
private TagsEditText sepia_element_all_of_tags, sepia_element_one_of_tags;
private MaterialSearchBar searchBar; private ActivitySepiaSearchBinding binding;
private ConstraintLayout filter_elements;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sepia_search); binding = ActivitySepiaSearchBinding.inflate(getLayoutInflater());
View rootView = binding.getRoot();
setContentView(rootView);
sepiaSearchVideo = new SepiaSearch(); sepiaSearchVideo = new SepiaSearch();
sepiaSearchChannel = new SepiaSearch(); sepiaSearchChannel = new SepiaSearch();
@ -76,21 +74,18 @@ public class SepiaSearchActivity extends AppCompatActivity {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Button filter = findViewById(R.id.filter); binding.filter.setOnClickListener(view -> {
filter_elements = findViewById(R.id.filter_elements); if (binding.filterElements.getVisibility() == View.VISIBLE) {
filter.setOnClickListener(view -> { binding.filterElements.setVisibility(View.GONE);
if (filter_elements.getVisibility() == View.VISIBLE) {
filter_elements.setVisibility(View.GONE);
} else { } else {
filter_elements.setVisibility(View.VISIBLE); binding.filterElements.setVisibility(View.VISIBLE);
} }
}); });
RadioGroup sepia_element_nsfw = findViewById(R.id.sepia_element_nsfw);
sepia_element_nsfw.setOnCheckedChangeListener((group, checkedId) -> sepiaSearchVideo.setNsfw(checkedId != R.id.sepia_element_nsfw_no));
RadioGroup radio_date = findViewById(R.id.radio_date); binding.sepiaElementNsfw.setOnCheckedChangeListener((group, checkedId) -> sepiaSearchVideo.setNsfw(checkedId != R.id.sepia_element_nsfw_no));
radio_date.setOnCheckedChangeListener((group, checkedId) -> {
binding.radioDate.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.sepia_element_published_date_today) { if (checkedId == R.id.sepia_element_published_date_today) {
Calendar cal = GregorianCalendar.getInstance(); Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.HOUR_OF_DAY, 0);
@ -122,8 +117,7 @@ public class SepiaSearchActivity extends AppCompatActivity {
}); });
RadioGroup duration = findViewById(R.id.duration); binding.duration.setOnCheckedChangeListener((group, checkedId) -> {
duration.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.sepia_element_duration_short) { if (checkedId == R.id.sepia_element_duration_short) {
sepiaSearchVideo.setDurationMin(0); sepiaSearchVideo.setDurationMin(0);
sepiaSearchVideo.setDurationMax(240); sepiaSearchVideo.setDurationMax(240);
@ -140,11 +134,10 @@ public class SepiaSearchActivity extends AppCompatActivity {
}); });
Spinner sort_by = findViewById(R.id.sort_by);
ArrayAdapter<String> adapterSortBy = new ArrayAdapter<>(SepiaSearchActivity.this, ArrayAdapter<String> adapterSortBy = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, getResources().getStringArray(R.array.sort_by_array)); android.R.layout.simple_spinner_dropdown_item, getResources().getStringArray(R.array.sort_by_array));
sort_by.setAdapter(adapterSortBy); binding.sortBy.setAdapter(adapterSortBy);
sort_by.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.sortBy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String orderby, channelOrderBy; String orderby, channelOrderBy;
@ -171,12 +164,6 @@ public class SepiaSearchActivity extends AppCompatActivity {
} }
}); });
Spinner sepia_element_category = findViewById(R.id.sepia_element_category);
Spinner sepia_element_license = findViewById(R.id.sepia_element_license);
Spinner sepia_element_language = findViewById(R.id.sepia_element_language);
sepia_element_all_of_tags = findViewById(R.id.sepia_element_all_of_tags);
sepia_element_one_of_tags = findViewById(R.id.sepia_element_one_of_tags);
LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories()); LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories());
LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences()); LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences());
@ -203,7 +190,7 @@ public class SepiaSearchActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterCatgories = new ArrayAdapter<>(SepiaSearchActivity.this, ArrayAdapter<String> adapterCatgories = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, categoriesA); android.R.layout.simple_spinner_dropdown_item, categoriesA);
sepia_element_category.setAdapter(adapterCatgories); binding.sepiaElementCategory.setAdapter(adapterCatgories);
//Populate licenses //Populate licenses
@ -222,7 +209,7 @@ public class SepiaSearchActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterLicenses = new ArrayAdapter<>(SepiaSearchActivity.this, ArrayAdapter<String> adapterLicenses = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, licensesA); android.R.layout.simple_spinner_dropdown_item, licensesA);
sepia_element_license.setAdapter(adapterLicenses); binding.sepiaElementLicense.setAdapter(adapterLicenses);
//Populate languages //Populate languages
String[] languagesA = new String[languages.size() + 1]; String[] languagesA = new String[languages.size() + 1];
@ -240,10 +227,10 @@ public class SepiaSearchActivity extends AppCompatActivity {
} }
ArrayAdapter<String> adapterLanguages = new ArrayAdapter<>(SepiaSearchActivity.this, ArrayAdapter<String> adapterLanguages = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, languagesA); android.R.layout.simple_spinner_dropdown_item, languagesA);
sepia_element_language.setAdapter(adapterLanguages); binding.sepiaElementLanguage.setAdapter(adapterLanguages);
sepia_element_license.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.sepiaElementLicense.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateLicensePosition(position); updateLicensePosition(position);
@ -255,7 +242,7 @@ public class SepiaSearchActivity extends AppCompatActivity {
} }
}); });
//Manage categories //Manage categories
sepia_element_category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.sepiaElementCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateCategoryPosition(position); updateCategoryPosition(position);
@ -268,7 +255,7 @@ public class SepiaSearchActivity extends AppCompatActivity {
}); });
//Manage languages //Manage languages
sepia_element_language.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { binding.sepiaElementLanguage.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateLanguagesPosition(position); updateLanguagesPosition(position);
@ -281,9 +268,7 @@ public class SepiaSearchActivity extends AppCompatActivity {
}); });
searchBar = findViewById(R.id.searchBar); binding.searchBar.setOnSearchActionListener(new MaterialSearchBar.OnSearchActionListener() {
searchBar.setOnSearchActionListener(new MaterialSearchBar.OnSearchActionListener() {
@Override @Override
public void onSearchStateChanged(boolean enabled) { public void onSearchStateChanged(boolean enabled) {
@ -299,22 +284,21 @@ public class SepiaSearchActivity extends AppCompatActivity {
makeSearch(); makeSearch();
} }
}); });
Button apply_filter = findViewById(R.id.apply_filter); binding.applyFilter.setOnClickListener(v -> makeSearch());
apply_filter.setOnClickListener(v -> makeSearch());
searchBar.openSearch(); binding.searchBar.openSearch();
} }
private void makeSearch() { private void makeSearch() {
hideKeyboard(SepiaSearchActivity.this); hideKeyboard(SepiaSearchActivity.this);
sepiaSearchVideo.setStart("0"); sepiaSearchVideo.setStart("0");
if (sepia_element_one_of_tags.getTags().size() > 0) { if (binding.sepiaElementOneOfTags.getTags().size() > 0) {
sepiaSearchVideo.setTagsOneOf(sepia_element_one_of_tags.getTags()); sepiaSearchVideo.setTagsOneOf(binding.sepiaElementOneOfTags.getTags());
} else { } else {
sepiaSearchVideo.setTagsOneOf(null); sepiaSearchVideo.setTagsOneOf(null);
} }
if (sepia_element_all_of_tags.getTags().size() > 0) { if (binding.sepiaElementAllOfTags.getTags().size() > 0) {
sepiaSearchVideo.setTagsAllOf(sepia_element_all_of_tags.getTags()); sepiaSearchVideo.setTagsAllOf(binding.sepiaElementAllOfTags.getTags());
} else { } else {
sepiaSearchVideo.setTagsAllOf(null); sepiaSearchVideo.setTagsAllOf(null);
} }
@ -322,8 +306,8 @@ public class SepiaSearchActivity extends AppCompatActivity {
Fragment fragment = getSupportFragmentManager().findFragmentByTag("SEPIA_SEARCH"); Fragment fragment = getSupportFragmentManager().findFragmentByTag("SEPIA_SEARCH");
if (fragment != null) if (fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit(); getSupportFragmentManager().beginTransaction().remove(fragment).commit();
filter_elements.setVisibility(View.GONE); binding.filterElements.setVisibility(View.GONE);
sepiaSearchVideo.setSearch(searchBar.getText()); sepiaSearchVideo.setSearch(binding.searchBar.getText());
DisplaySepiaSearchFragment displaySepiaSearchFragment = new DisplaySepiaSearchFragment(); DisplaySepiaSearchFragment displaySepiaSearchFragment = new DisplaySepiaSearchFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("sepiaSearchVideo", sepiaSearchVideo); bundle.putParcelable("sepiaSearchVideo", sepiaSearchVideo);

View File

@ -14,6 +14,7 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html; import android.text.Html;
@ -104,6 +105,7 @@ public class ShowAccountActivity extends AppCompatActivity {
if (!Helper.isLoggedIn(ShowAccountActivity.this)) { if (!Helper.isLoggedIn(ShowAccountActivity.this)) {
menu.findItem(R.id.action_mute).setVisible(false); menu.findItem(R.id.action_mute).setVisible(false);
} }
menu.findItem(R.id.action_display_account).setVisible(false);
return true; return true;
} }
@ -133,6 +135,17 @@ public class ShowAccountActivity extends AppCompatActivity {
}); });
AlertDialog alertDialog = dialogBuilder.create(); AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show(); alertDialog.show();
} else if (item.getItemId() == R.id.action_share && account != null) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.shared_via));
String extra_text = account.getUrl();
sendIntent.putExtra(Intent.EXTRA_TEXT, extra_text);
sendIntent.setType("text/plain");
try {
startActivity(Intent.createChooser(sendIntent, getString(R.string.share_with)));
} catch (Exception e) {
Toasty.error(ShowAccountActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
}
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@ -275,13 +288,12 @@ public class ShowAccountActivity extends AppCompatActivity {
if (position == 0) { if (position == 0) {
DisplayChannelsFragment displayChannelsFragment = new DisplayChannelsFragment(); DisplayChannelsFragment displayChannelsFragment = new DisplayChannelsFragment();
bundle.putString("name", account.getAcct()); bundle.putString("name", account.getAcct());
bundle.putBoolean("myChannels", false);
displayChannelsFragment.setArguments(bundle); displayChannelsFragment.setArguments(bundle);
return displayChannelsFragment; return displayChannelsFragment;
} }
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment(); DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.ACCOUNT_VIDEOS); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.ACCOUNT_VIDEOS);
bundle.putString("channelId", account.getAcct()); bundle.putParcelable("account", account);
bundle.putString("peertube_instance", account.getHost()); bundle.putString("peertube_instance", account.getHost());
displayVideosFragment.setArguments(bundle); displayVideosFragment.setArguments(bundle);
return displayVideosFragment; return displayVideosFragment;

View File

@ -17,6 +17,7 @@ package app.fedilab.fedilabtube;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html; import android.text.Html;
@ -54,10 +55,14 @@ import java.util.Map;
import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.AccountData;
import app.fedilab.fedilabtube.client.data.ChannelData.Channel; import app.fedilab.fedilabtube.client.data.ChannelData.Channel;
import app.fedilab.fedilabtube.drawer.OwnAccountsAdapter;
import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment; import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
import app.fedilab.fedilabtube.viewmodel.PostActionsVM; import app.fedilab.fedilabtube.viewmodel.PostActionsVM;
import app.fedilab.fedilabtube.viewmodel.RelationshipVM; import app.fedilab.fedilabtube.viewmodel.RelationshipVM;
@ -65,6 +70,7 @@ import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY; import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY;
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.SURFING;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT;
@ -122,6 +128,57 @@ public class ShowChannelActivity extends AppCompatActivity {
ChannelsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(ChannelsVM.class); ChannelsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(ChannelsVM.class);
viewModel.get(sepiaSearch ? peertubeInstance : null, CHANNEL, channelAcct == null ? channel.getAcct() : channelAcct).observe(ShowChannelActivity.this, this::manageViewAccounts); viewModel.get(sepiaSearch ? peertubeInstance : null, CHANNEL, channelAcct == null ? channel.getAcct() : channelAcct).observe(ShowChannelActivity.this, this::manageViewAccounts);
manageChannel(); manageChannel();
if (MainActivity.typeOfConnection == MainActivity.TypeOfConnection.SURFING) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int[][] states = new int[][]{
new int[]{android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled}, // disabled
new int[]{-android.R.attr.state_checked}, // unchecked
new int[]{android.R.attr.state_pressed} // pressed
};
int[] colors = new int[]{
ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()),
ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()),
ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()),
ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent())
};
account_follow.setBackgroundTintList(new ColorStateList(states, colors));
}
account_follow.setText(getString(R.string.action_follow));
account_follow.setEnabled(true);
new Thread(() -> {
try {
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<AccountData.Account> accounts = new AccountDAO(ShowChannelActivity.this, db).getAllAccount();
runOnUiThread(() -> {
account_follow.setVisibility(View.VISIBLE);
account_follow.setOnClickListener(v -> {
AlertDialog.Builder builderSingle = new AlertDialog.Builder(ShowChannelActivity.this);
builderSingle.setTitle(getString(R.string.list_of_accounts));
if (accounts != null) {
final OwnAccountsAdapter accountsListAdapter = new OwnAccountsAdapter(ShowChannelActivity.this, accounts);
builderSingle.setAdapter(accountsListAdapter, (dialog, which) -> {
new Thread(() -> {
try {
RetrofitPeertubeAPI peertubeAPI = new RetrofitPeertubeAPI(ShowChannelActivity.this, accounts.get(which).getHost(), accounts.get(which).getToken());
peertubeAPI.post(FOLLOW, channel.getAcct(), null);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
});
}
builderSingle.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderSingle.show();
});
});
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
} }
@Override @Override
@ -159,6 +216,24 @@ public class ShowChannelActivity extends AppCompatActivity {
}); });
androidx.appcompat.app.AlertDialog alertDialog = dialogBuilder.create(); androidx.appcompat.app.AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show(); alertDialog.show();
} else if (item.getItemId() == R.id.action_share && channel != null) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.shared_via));
String extra_text = channel.getUrl();
sendIntent.putExtra(Intent.EXTRA_TEXT, extra_text);
sendIntent.setType("text/plain");
try {
startActivity(Intent.createChooser(sendIntent, getString(R.string.share_with)));
} catch (Exception e) {
Toasty.error(ShowChannelActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
}
} else if (item.getItemId() == R.id.action_display_account) {
Bundle b = new Bundle();
Intent intent = new Intent(ShowChannelActivity.this, ShowAccountActivity.class);
b.putParcelable("account", channel.getOwnerAccount());
b.putString("accountAcct", channel.getOwnerAccount().getAcct());
intent.putExtras(b);
startActivity(intent);
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@ -167,7 +242,7 @@ public class ShowChannelActivity extends AppCompatActivity {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
String accountIdRelation = channel.getAcct(); String accountIdRelation = channel.getAcct();
if (isLoggedIn(ShowChannelActivity.this) && !sepiaSearch) { if (isLoggedIn(ShowChannelActivity.this)) {
RelationshipVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(RelationshipVM.class); RelationshipVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(RelationshipVM.class);
List<String> uids = new ArrayList<>(); List<String> uids = new ArrayList<>();
uids.add(accountIdRelation); uids.add(accountIdRelation);
@ -294,7 +369,7 @@ public class ShowChannelActivity extends AppCompatActivity {
//Manages the visibility of the button //Manages the visibility of the button
private void manageButtonVisibility() { private void manageButtonVisibility() {
if (relationship == null) if (relationship == null || MainActivity.typeOfConnection == SURFING)
return; return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -418,7 +493,7 @@ public class ShowChannelActivity extends AppCompatActivity {
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment(); DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.CHANNEL_VIDEOS); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.CHANNEL_VIDEOS);
bundle.putString("channelId", channel.getAcct()); bundle.putParcelable("channel", channel);
bundle.putString("peertube_instance", channel.getHost()); bundle.putString("peertube_instance", channel.getHost());
bundle.putBoolean("sepia_search", sepiaSearch); bundle.putBoolean("sepia_search", sepiaSearch);
displayVideosFragment.setArguments(bundle); displayVideosFragment.setArguments(bundle);

View File

@ -14,26 +14,45 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.app.AlertDialog;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider;
import org.jetbrains.annotations.NotNull;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.databinding.ActivityVideosTimelineBinding;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import static app.fedilab.fedilabtube.viewmodel.TimelineVM.TimelineType.HISTORY;
public class VideosTimelineActivity extends AppCompatActivity { public class VideosTimelineActivity extends AppCompatActivity {
private TimelineVM.TimelineType type; private TimelineVM.TimelineType type;
private DisplayVideosFragment displayVideosFragment;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result); ActivityVideosTimelineBinding binding = ActivityVideosTimelineBinding.inflate(getLayoutInflater());
View mainView = binding.getRoot();
setContentView(mainView);
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -41,33 +60,116 @@ public class VideosTimelineActivity extends AppCompatActivity {
Bundle b = getIntent().getExtras(); Bundle b = getIntent().getExtras();
if (b != null) if (b != null)
type = (TimelineVM.TimelineType) b.get("type"); type = (TimelineVM.TimelineType) b.get("type");
displayVideosFragment = null;
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (savedInstanceState == null) {
displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, type);
displayVideosFragment.setArguments(bundle);
ft.add(R.id.container, displayVideosFragment).addToBackStack(null).commit();
}
if (type == TimelineVM.TimelineType.MY_VIDEOS) { if (type == TimelineVM.TimelineType.MY_VIDEOS) {
setTitle(R.string.my_videos); setTitle(R.string.my_videos);
} else if (type == TimelineVM.TimelineType.HISTORY) { } else if (type == HISTORY) {
setTitle(R.string.my_history); setTitle(R.string.my_history);
//TODO: uncomment when available
// binding.historyFilter.setVisibility(View.VISIBLE);
binding.historyFilterAll.setOnClickListener(v -> historyFilter(null));
binding.historyFilterToday.setOnClickListener(v -> {
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.getTime();
historyFilter(cal.getTime());
});
binding.historyFilterLast7Days.setOnClickListener(v -> {
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DAY_OF_YEAR, -7);
cal.getTime();
historyFilter(cal.getTime());
});
} else if (type == TimelineVM.TimelineType.MOST_LIKED) { } else if (type == TimelineVM.TimelineType.MOST_LIKED) {
setTitle(R.string.title_most_liked); setTitle(R.string.title_most_liked);
} }
if (savedInstanceState == null) {
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment(); }
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, type); private void historyFilter(Date date) {
displayVideosFragment.setArguments(bundle); String startDate = null;
if (date != null) {
SimpleDateFormat fmtOut = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
startDate = fmtOut.format(date);
}
if (displayVideosFragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, displayVideosFragment).commit(); displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, HISTORY);
bundle.putSerializable("startDate", startDate);
displayVideosFragment.setArguments(bundle);
ft.replace(R.id.container, displayVideosFragment);
ft.addToBackStack(null);
ft.commit();
} }
} }
@Override
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
if (type == HISTORY) {
getMenuInflater().inflate(R.menu.main_history, menu);
return true;
} else {
return super.onCreateOptionsMenu(menu);
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) { if (item.getItemId() == android.R.id.home) {
finish(); finish();
return true; return true;
} else if (item.getItemId() == R.id.action_delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(VideosTimelineActivity.this);
builder.setTitle(R.string.delete_history);
builder.setMessage(R.string.delete_history_confirm);
builder.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(R.string.delete, (dialog, which) -> {
TimelineVM viewModelFeeds = new ViewModelProvider(VideosTimelineActivity.this).get(TimelineVM.class);
viewModelFeeds.deleterHistory().observe(VideosTimelineActivity.this, this::manageVIewVideos);
dialog.dismiss();
})
.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
.show();
return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void manageVIewVideos(APIResponse apiResponse) {
if (type == HISTORY) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
displayVideosFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, HISTORY);
displayVideosFragment.setArguments(bundle);
ft.replace(R.id.container, displayVideosFragment);
ft.addToBackStack(null);
ft.commit();
}
}
} }

View File

@ -0,0 +1,53 @@
package app.fedilab.fedilabtube.client;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
public class MenuItemVideo {
int icon;
String title;
actionType action;
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public actionType getAction() {
return action;
}
public void setAction(actionType action) {
this.action = action;
}
public enum actionType {
RESOLUTION,
SPEED,
CAPTION,
AUTONEXT
}
}

View File

@ -29,6 +29,7 @@ import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.data.VideoPlaylistData; import app.fedilab.fedilabtube.client.data.VideoPlaylistData;
import app.fedilab.fedilabtube.client.entities.CaptionsParams; import app.fedilab.fedilabtube.client.entities.CaptionsParams;
import app.fedilab.fedilabtube.client.entities.ChannelParams; import app.fedilab.fedilabtube.client.entities.ChannelParams;
import app.fedilab.fedilabtube.client.entities.NotificationSettings;
import app.fedilab.fedilabtube.client.entities.Oauth; import app.fedilab.fedilabtube.client.entities.Oauth;
import app.fedilab.fedilabtube.client.entities.OverviewVideo; import app.fedilab.fedilabtube.client.entities.OverviewVideo;
import app.fedilab.fedilabtube.client.entities.PlaylistExist; import app.fedilab.fedilabtube.client.entities.PlaylistExist;
@ -65,6 +66,14 @@ public interface PeertubeService {
@GET(".well-known/nodeinfo") @GET(".well-known/nodeinfo")
Call<WellKnownNodeinfo> getWellKnownNodeinfo(); Call<WellKnownNodeinfo> getWellKnownNodeinfo();
//Instance info
@GET("config/about")
Call<InstanceData.InstanceInfo> configAbout();
//Instance config
@GET("config")
Call<InstanceData.InstanceConfig> config();
@GET("{nodeInfoPath}") @GET("{nodeInfoPath}")
Call<WellKnownNodeinfo.NodeInfo> getNodeinfo(@Path(value = "nodeInfoPath", encoded = true) String nodeInfoPath); Call<WellKnownNodeinfo.NodeInfo> getNodeinfo(@Path(value = "nodeInfoPath", encoded = true) String nodeInfoPath);
@ -114,6 +123,45 @@ public interface PeertubeService {
@GET("users/me") @GET("users/me")
Call<UserMe> verifyCredentials(@Header("Authorization") String credentials); Call<UserMe> verifyCredentials(@Header("Authorization") String credentials);
@GET("users/me/video-quota-used")
Call<UserMe.VideoQuota> getVideoQuota(@Header("Authorization") String credentials);
@FormUrlEncoded
@PUT("videos/{id}/watching")
Call<String> addToHistory(
@Header("Authorization") String credentials,
@Path("id") String id,
@Field("currentTime") long currentTime);
@FormUrlEncoded
@PUT("users/me")
Call<String> updateUser(
@Header("Authorization") String credentials,
@Field("videosHistoryEnabled") Boolean videosHistoryEnabled,
@Field("autoPlayVideo") Boolean autoPlayVideo,
@Field("autoPlayNextVideo") Boolean autoPlayNextVideo,
@Field("webTorrentEnabled") Boolean webTorrentEnabled,
@Field("videoLanguages") List<String> videoLanguages,
@Field("description") String description,
@Field("displayName") String displayName,
@Field("nsfwPolicy") String nsfwPolicy
);
@Multipart
@POST("video-channels/{channelHandle}/avatar/pick")
Call<UserMe.AvatarResponse> updateChannelProfilePicture(
@Header("Authorization") String credentials,
@Path("channelHandle") String channelHandle,
@Part MultipartBody.Part avatarfile);
@Multipart
@POST("users/me/avatar/pick")
Call<UserMe.AvatarResponse> updateProfilePicture(
@Header("Authorization") String credentials,
@Part MultipartBody.Part avatarfile);
//Timelines Authenticated //Timelines Authenticated
//Subscriber timeline //Subscriber timeline
@GET("users/me/subscriptions/videos?sort=-publishedAt") @GET("users/me/subscriptions/videos?sort=-publishedAt")
@ -141,21 +189,60 @@ public interface PeertubeService {
//History //History
@GET("users/me/history/videos") @GET("users/me/history/videos")
Call<VideoData> getHistory(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count); Call<VideoData> getHistory(
@Header("Authorization") String credentials,
@Query("start") String maxId,
@Query("count") String count,
@Query("startDate") String startDate,
@Query("endDate") String endDate
);
@POST("users/me/history/videos/remove")
Call<String> deleteHistory(
@Header("Authorization") String credentials);
//Search videos
@GET("search/videos")
Call<VideoData> searchVideos(
@Header("Authorization") String credentials,
@Query("search") String search,
@Query("start") String maxId,
@Query("count") String count);
//Search channels
@GET("search/video-channels")
Call<ChannelData> searchChannels(
@Header("Authorization") String credentials,
@Query("search") String search,
@Query("searcharget") String searchTarget,
@Query("start") String maxId,
@Query("count") String count);
//Search //Search
@GET("search/videos") @GET("search/videos")
Call<VideoData> searchVideos(@Header("Authorization") String credentials, @Query("search") String search, @Query("start") String maxId, @Query("count") String count); Call<VideoData> searchNextVideo(
@Header("Authorization") String credentials,
@Query("tagsOneOf") List<String> tagsOneOf,
@Query("start") String maxId,
@Query("count") String count);
//Get notifications //Get notifications
@GET("users/me/notifications") @GET("users/me/notifications")
Call<NotificationData> getNotifications(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("since_id") String sinceId); Call<NotificationData> getNotifications(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("since_id") String sinceId);
//Update Notification settings
@PUT("users/me/notification-settings")
Call<String> updateNotifications(@Header("Authorization") String credentials, @Body NotificationSettings notificationSettings);
//Get/Post/Update/Delete video //Get/Post/Update/Delete video
//Get a video //Get a video
@GET("videos/{id}") @GET("videos/{id}")
Call<VideoData.Video> getVideo(@Path("id") String id); Call<VideoData.Video> getVideo(@Path("id") String id);
//Get a video description
@GET("videos/{uuid}/description")
Call<VideoData.Description> getVideoDescription(@Path("uuid") String uuid);
@GET("videos/{id}") @GET("videos/{id}")
Call<VideoData.Video> getMyVideo(@Header("Authorization") String credentials, @Path("id") String id); Call<VideoData.Video> getMyVideo(@Header("Authorization") String credentials, @Path("id") String id);

View File

@ -19,11 +19,20 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.webkit.MimeTypeMap;
import java.io.File; import androidx.documentfile.provider.DocumentFile;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
@ -61,6 +70,7 @@ import app.fedilab.fedilabtube.client.entities.Rating;
import app.fedilab.fedilabtube.client.entities.Report; import app.fedilab.fedilabtube.client.entities.Report;
import app.fedilab.fedilabtube.client.entities.Token; import app.fedilab.fedilabtube.client.entities.Token;
import app.fedilab.fedilabtube.client.entities.UserMe; import app.fedilab.fedilabtube.client.entities.UserMe;
import app.fedilab.fedilabtube.client.entities.UserSettings;
import app.fedilab.fedilabtube.client.entities.VideoParams; import app.fedilab.fedilabtube.client.entities.VideoParams;
import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
@ -106,6 +116,7 @@ public class RetrofitPeertubeAPI {
count = String.valueOf(sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE)); count = String.valueOf(sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE));
} }
public static void updateCredential(Activity activity, String token, String client_id, String client_secret, String refresh_token, String host) { public static void updateCredential(Activity activity, String token, String client_id, String client_secret, String refresh_token, String host) {
new Thread(() -> { new Thread(() -> {
AccountData.Account account; AccountData.Account account;
@ -161,9 +172,9 @@ public class RetrofitPeertubeAPI {
} }
private String getToken() { private String getToken() {
if( token != null) { if (token != null) {
return "Bearer " + token; return "Bearer " + token;
}else{ } else {
return null; return null;
} }
} }
@ -232,6 +243,33 @@ public class RetrofitPeertubeAPI {
return null; return null;
} }
/**
* Retrieve notifications
*
* @return APIResponse
*/
public APIResponse getNotifications() {
APIResponse apiResponse = new APIResponse();
PeertubeService peertubeService = init();
Call<NotificationData> notificationsCall = peertubeService.getNotifications("Bearer " + token, "0", "40", null);
try {
Response<NotificationData> response = notificationsCall.execute();
if (response.isSuccessful() && response.body() != null) {
apiResponse.setPeertubeNotifications(response.body().data);
} else {
setError(apiResponse, response.code(), response.errorBody());
}
} catch (IOException e) {
Error error = new Error();
error.setError(_context.getString(R.string.toast_error));
apiResponse.setError(error);
e.printStackTrace();
}
return apiResponse;
}
/** /**
* Retrieve notifications * Retrieve notifications
* *
@ -315,6 +353,51 @@ public class RetrofitPeertubeAPI {
return apiResponse; return apiResponse;
} }
public APIResponse deleteHistory() {
APIResponse apiResponse = new APIResponse();
PeertubeService peertubeService = init();
Call<String> stringCall = peertubeService.deleteHistory(getToken());
if (stringCall != null) {
try {
Response<String> response = stringCall.execute();
if (response.isSuccessful() && response.body() != null) {
apiResponse.setActionReturn(response.body());
} else {
setError(apiResponse, response.code(), response.errorBody());
}
} catch (IOException e) {
Error error = new Error();
error.setError(_context.getString(R.string.toast_error));
apiResponse.setError(error);
e.printStackTrace();
}
}
return apiResponse;
}
public APIResponse getHistory(String max_id, String startDate, String endDate) {
APIResponse apiResponse = new APIResponse();
PeertubeService peertubeService = init();
Call<VideoData> videoCall = peertubeService.getHistory(getToken(), max_id, count, startDate, endDate);
if (videoCall != null) {
try {
Response<VideoData> response = videoCall.execute();
if (response.isSuccessful() && response.body() != null) {
apiResponse.setPeertubes(response.body().data);
} else {
setError(apiResponse, response.code(), response.errorBody());
}
} catch (IOException e) {
Error error = new Error();
error.setError(_context.getString(R.string.toast_error));
apiResponse.setError(error);
e.printStackTrace();
}
}
return apiResponse;
}
public APIResponse getTL(TimelineVM.TimelineType timelineType, String max_id, String forAccount) { public APIResponse getTL(TimelineVM.TimelineType timelineType, String max_id, String forAccount) {
APIResponse apiResponse = new APIResponse(); APIResponse apiResponse = new APIResponse();
PeertubeService peertubeService = init(); PeertubeService peertubeService = init();
@ -344,7 +427,7 @@ public class RetrofitPeertubeAPI {
videoCall = peertubeService.getTrendingVideos(getToken(), max_id, count, filter); videoCall = peertubeService.getTrendingVideos(getToken(), max_id, count, filter);
break; break;
case HISTORY: case HISTORY:
videoCall = peertubeService.getHistory(getToken(), max_id, count); videoCall = peertubeService.getHistory(getToken(), max_id, count, null, null);
break; break;
case RECENT: case RECENT:
videoCall = peertubeService.getRecentlyAddedVideos(getToken(), max_id, count, filter); videoCall = peertubeService.getRecentlyAddedVideos(getToken(), max_id, count, filter);
@ -419,6 +502,111 @@ public class RetrofitPeertubeAPI {
return apiResponse; return apiResponse;
} }
/**
* Update history
*
* @param videoId String
* @param currentTime int
*/
public void updateHistory(String videoId, long currentTime) {
APIResponse apiResponse = new APIResponse();
PeertubeService peertubeService = init();
Call<String> updateUser = peertubeService.addToHistory(getToken(),
videoId,
currentTime
);
try {
Response<String> response = updateUser.execute();
if (response.isSuccessful()) {
apiResponse.setActionReturn(response.body());
} else {
setError(apiResponse, response.code(), response.errorBody());
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Update account information
*
* @param userSettings UserSettings
*/
public UserMe.AvatarResponse updateUser(UserSettings userSettings) throws IOException, Error {
APIResponse apiResponse = new APIResponse();
UserMe.AvatarResponse avatarResponse = null;
PeertubeService peertubeService = init();
Call<String> updateNotifications = peertubeService.updateNotifications(getToken(), userSettings.getNotificationSettings());
Response<String> responseNotif = updateNotifications.execute();
Call<String> updateUser = peertubeService.updateUser(getToken(),
userSettings.isVideosHistoryEnabled(),
userSettings.isAutoPlayVideo(),
userSettings.isAutoPlayNextVideo(),
userSettings.isWebTorrentEnabled(),
userSettings.getVideoLanguages(),
userSettings.getDescription(),
userSettings.getDisplayName(),
userSettings.getNsfwPolicy()
);
Response<String> response = updateUser.execute();
if (response.isSuccessful()) {
apiResponse.setActionReturn(response.body());
} else {
setError(apiResponse, response.code(), response.errorBody());
Error error = new Error();
error.setStatusCode(response.code());
if (response.errorBody() != null) {
error.setError(response.errorBody().string());
} else {
error.setError(_context.getString(R.string.toast_error));
}
throw error;
}
if (userSettings.getAvatarfile() != null) {
MultipartBody.Part bodyThumbnail = createFile("avatarfile", userSettings.getAvatarfile(), userSettings.getFileName());
Call<UserMe.AvatarResponse> updateProfilePicture = peertubeService.updateProfilePicture(getToken(), bodyThumbnail);
Response<UserMe.AvatarResponse> responseAvatar = updateProfilePicture.execute();
if (response.isSuccessful()) {
avatarResponse = responseAvatar.body();
} else {
setError(apiResponse, response.code(), response.errorBody());
Error error = new Error();
error.setStatusCode(response.code());
if (response.errorBody() != null) {
error.setError(response.errorBody().string());
} else {
error.setError(_context.getString(R.string.toast_error));
}
throw error;
}
}
return avatarResponse;
}
private MultipartBody.Part createFile(@NotNull String paramName, @NotNull Uri uri, String filename) throws IOException {
InputStream inputStream = _context.getContentResolver().openInputStream(uri);
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
byte[] imageBytes = byteBuffer.toByteArray();
String mime = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
if (mime == null || mime.trim().length() == 0) {
mime = "png";
}
if (filename == null) {
filename = "my_image." + mime;
}
RequestBody requestFile = RequestBody.create(imageBytes, MediaType.parse("image/" + mime));
return MultipartBody.Part.createFormData(paramName, filename, requestFile);
}
/** /**
* Check if users via their uris are following the authenticated user * Check if users via their uris are following the authenticated user
@ -468,6 +656,67 @@ public class RetrofitPeertubeAPI {
return apiResponse; return apiResponse;
} }
/**
* About the instance
*
* @return AboutInstance
*/
public InstanceData.AboutInstance getAboutInstance() {
PeertubeService peertubeService = init();
Call<InstanceData.InstanceInfo> about = peertubeService.configAbout();
try {
Response<InstanceData.InstanceInfo> response = about.execute();
if (response.isSuccessful() && response.body() != null) {
return response.body().getInstance();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Config of the instance
*
* @return InstanceConfig
*/
public InstanceData.InstanceConfig getConfigInstance() {
PeertubeService peertubeService = init();
Call<InstanceData.InstanceConfig> config = peertubeService.config();
try {
Response<InstanceData.InstanceConfig> response = config.execute();
if (response.isSuccessful() && response.body() != null) {
return response.body();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Get video quota
*
* @return UserMe.VideoQuota
*/
public UserMe.VideoQuota getVideoQuota() {
PeertubeService peertubeService = init();
Call<UserMe.VideoQuota> videoQuotaCall = peertubeService.getVideoQuota(getToken());
try {
Response<UserMe.VideoQuota> response = videoQuotaCall.execute();
if (response.isSuccessful() && response.body() != null) {
return response.body();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/** /**
* Returns informations about Peertube such privacies, licenses, etc. * Returns informations about Peertube such privacies, licenses, etc.
* *
@ -643,15 +892,16 @@ public class RetrofitPeertubeAPI {
return apiResponse; return apiResponse;
} }
/** /**
* Retrieves peertube search *synchronously* * Retrieves next peertube videos *synchronously*
* *
* @param query String search * @param tags List<String> search
* @return APIResponse * @return APIResponse
*/ */
public APIResponse searchPeertube(String query, String max_id) { public APIResponse searchNextVideos(List<String> tags) {
PeertubeService peertubeService = init(); PeertubeService peertubeService = init();
Call<VideoData> searchVideosCall = peertubeService.searchVideos(getToken(), query, max_id, count); Call<VideoData> searchVideosCall = peertubeService.searchNextVideo(getToken(), tags, "0", "20");
APIResponse apiResponse = new APIResponse(); APIResponse apiResponse = new APIResponse();
try { try {
Response<VideoData> response = searchVideosCall.execute(); Response<VideoData> response = searchVideosCall.execute();
@ -669,6 +919,61 @@ public class RetrofitPeertubeAPI {
return apiResponse; return apiResponse;
} }
/**
* Retrieves peertube search *synchronously*
*
* @param query String search
* @return APIResponse
*/
public APIResponse searchPeertube(String query, String max_id) {
PeertubeService peertubeService = init();
Call<VideoData> searchVideosCall = peertubeService.searchVideos(getToken(), query, max_id, count);
APIResponse apiResponse = new APIResponse();
try {
Response<VideoData> response = searchVideosCall.execute();
if (response.isSuccessful() && response.body() != null) {
apiResponse.setPeertubes(response.body().data);
} else {
setError(apiResponse, response.code(), response.errorBody());
}
} catch (IOException e) {
Error error = new Error();
error.setError(_context.getString(R.string.toast_error));
apiResponse.setError(error);
e.printStackTrace();
}
return apiResponse;
}
/**
* Retrieves channels search *synchronously*
*
* @param query String search
* @return APIResponse
*/
public APIResponse searchChannels(String query, String max_id) {
PeertubeService peertubeService = init();
Call<ChannelData> searchChannelsCall = peertubeService.searchChannels(getToken(), query, "local", max_id, count);
APIResponse apiResponse = new APIResponse();
try {
Response<ChannelData> response = searchChannelsCall.execute();
if (response.isSuccessful() && response.body() != null) {
apiResponse.setChannels(response.body().data);
} else {
setError(apiResponse, response.code(), response.errorBody());
}
} catch (IOException e) {
Error error = new Error();
error.setError(_context.getString(R.string.toast_error));
apiResponse.setError(error);
e.printStackTrace();
}
return apiResponse;
}
/*** /***
* Verifiy credential of the authenticated user *synchronously* * Verifiy credential of the authenticated user *synchronously*
* @return Account * @return Account
@ -728,34 +1033,47 @@ public class RetrofitPeertubeAPI {
* @param previewfile File preview * @param previewfile File preview
* @return APIResponse * @return APIResponse
*/ */
public APIResponse updateVideo(String videoId, VideoParams videoParams, File thumbnail, File previewfile) { public APIResponse updateVideo(String videoId, VideoParams videoParams, Uri thumbnail, Uri previewfile) {
PeertubeService peertubeService = init(); PeertubeService peertubeService = init();
MultipartBody.Part bodyThumbnail = null; MultipartBody.Part bodyThumbnail = null;
MultipartBody.Part bodyPreviewfile = null; MultipartBody.Part bodyPreviewfile = null;
if (thumbnail != null) { try {
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), thumbnail); if (thumbnail != null) {
bodyThumbnail = MultipartBody.Part.createFormData("image", thumbnail.getName(), requestFile); DocumentFile documentFile = DocumentFile.fromSingleUri(_context, thumbnail);
String thumbnailName = null;
if (documentFile != null) {
thumbnailName = documentFile.getName();
}
bodyThumbnail = createFile("avatarfile", thumbnail, thumbnailName);
}
if (previewfile != null && thumbnail != null) {
DocumentFile documentFile = DocumentFile.fromSingleUri(_context, thumbnail);
String previewfileName = null;
if (documentFile != null) {
previewfileName = documentFile.getName();
}
bodyPreviewfile = createFile("image", previewfile, previewfileName);
}
} catch (IOException e) {
e.printStackTrace();
} }
if (previewfile != null) { RequestBody channelId = RequestBody.create(videoParams.getChannelId(), MediaType.parse("text/plain"));
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), previewfile); RequestBody description = RequestBody.create(videoParams.getDescription(), MediaType.parse("text/plain"));
bodyPreviewfile = MultipartBody.Part.createFormData("image", previewfile.getName(), requestFile); RequestBody language = RequestBody.create(videoParams.getLanguage(), MediaType.parse("text/plain"));
} RequestBody license = RequestBody.create(videoParams.getLicence(), MediaType.parse("text/plain"));
RequestBody channelId = RequestBody.create(MediaType.parse("text/plain"), videoParams.getChannelId()); RequestBody name = RequestBody.create(videoParams.getName(), MediaType.parse("text/plain"));
RequestBody description = RequestBody.create(MediaType.parse("text/plain"), videoParams.getDescription());
RequestBody language = RequestBody.create(MediaType.parse("text/plain"), videoParams.getLanguage());
RequestBody license = RequestBody.create(MediaType.parse("text/plain"), videoParams.getLicence());
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), videoParams.getName());
List<RequestBody> tags = null; List<RequestBody> tags = null;
if (videoParams.getTags() != null && videoParams.getTags().size() > 0) { if (videoParams.getTags() != null && videoParams.getTags().size() > 0) {
tags = new ArrayList<>(); tags = new ArrayList<>();
for (String tag : videoParams.getTags()) { for (String tag : videoParams.getTags()) {
tags.add(RequestBody.create(MediaType.parse("text/plain"), tag)); tags.add(RequestBody.create(tag, MediaType.parse("text/plain")));
} }
} }
RequestBody support = null; RequestBody support = null;
if (videoParams.getSupport() != null) { if (videoParams.getSupport() != null) {
support = RequestBody.create(MediaType.parse("text/plain"), videoParams.getSupport()); support = RequestBody.create(videoParams.getSupport(), MediaType.parse("text/plain"));
} }
@ -883,6 +1201,25 @@ public class RetrofitPeertubeAPI {
} }
/**
* Get video description
*
* @param uuid String (pagination)
* @return APIResponse
*/
public VideoData.Description getVideoDescription(String uuid) {
PeertubeService peertubeService = init();
Call<VideoData.Description> videoDescription = peertubeService.getVideoDescription(uuid);
try {
Response<VideoData.Description> response = videoDescription.execute();
if (response.isSuccessful() && response.body() != null) {
return response.body();
}
} catch (IOException ignored) {
}
return null;
}
/** /**
* Get muted accounts * Get muted accounts
* *
@ -947,7 +1284,7 @@ public class RetrofitPeertubeAPI {
* @param channelParams PlaylistParams * @param channelParams PlaylistParams
* @return APIResponse * @return APIResponse
*/ */
public APIResponse createOrUpdateChannel(ChannelsVM.action apiAction, String channelId, ChannelParams channelParams) { public APIResponse createOrUpdateChannel(ChannelsVM.action apiAction, String channelId, ChannelParams channelParams, Uri avatar) {
PeertubeService peertubeService = init(); PeertubeService peertubeService = init();
APIResponse apiResponse = new APIResponse(); APIResponse apiResponse = new APIResponse();
@ -970,6 +1307,21 @@ public class RetrofitPeertubeAPI {
setError(apiResponse, response.code(), response.errorBody()); setError(apiResponse, response.code(), response.errorBody());
} }
} }
if (avatar != null) {
DocumentFile documentFile = DocumentFile.fromSingleUri(_context, avatar);
String avatarfileName = null;
if (documentFile != null) {
avatarfileName = documentFile.getName();
}
MultipartBody.Part bodyThumbnail = createFile("avatarfile", avatar, avatarfileName);
Call<UserMe.AvatarResponse> updateProfilePicture = peertubeService.updateChannelProfilePicture(getToken(), channelId, bodyThumbnail);
Response<UserMe.AvatarResponse> responseAvatar = updateProfilePicture.execute();
if (responseAvatar.isSuccessful()) {
UserMe.AvatarResponse avatarResponse = responseAvatar.body();
} else {
setError(apiResponse, responseAvatar.code(), responseAvatar.errorBody());
}
}
} catch (IOException e) { } catch (IOException e) {
Error error = new Error(); Error error = new Error();
error.setError(_context.getString(R.string.toast_error)); error.setError(_context.getString(R.string.toast_error));
@ -1093,21 +1445,31 @@ public class RetrofitPeertubeAPI {
* @param playlistParams PlaylistParams * @param playlistParams PlaylistParams
* @return APIResponse * @return APIResponse
*/ */
public APIResponse createOrUpdatePlaylist(PlaylistsVM.action apiAction, String playlistId, PlaylistParams playlistParams, File thumbnail) { public APIResponse createOrUpdatePlaylist(PlaylistsVM.action apiAction, String playlistId, PlaylistParams playlistParams, Uri thumbnail) {
PeertubeService peertubeService = init(); PeertubeService peertubeService = init();
APIResponse apiResponse = new APIResponse(); APIResponse apiResponse = new APIResponse();
MultipartBody.Part body = null; MultipartBody.Part body = null;
MultipartBody.Part bodyThumbnail = null;
if (thumbnail != null) { if (thumbnail != null) {
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), thumbnail); DocumentFile documentFile = DocumentFile.fromSingleUri(_context, thumbnail);
body = MultipartBody.Part.createFormData("image", thumbnail.getName(), requestFile); String avatarfileName = null;
if (documentFile != null) {
avatarfileName = documentFile.getName();
}
try {
bodyThumbnail = createFile("thumbnailfile", thumbnail, avatarfileName);
} catch (IOException e) {
e.printStackTrace();
}
} }
try { try {
RequestBody displayName = RequestBody.create(MediaType.parse("text/plain"), playlistParams.getDisplayName()); RequestBody displayName = RequestBody.create(playlistParams.getDisplayName(), MediaType.parse("text/plain"));
RequestBody description = RequestBody.create(MediaType.parse("text/plain"), playlistParams.getDescription()); RequestBody description = RequestBody.create(playlistParams.getDescription(), MediaType.parse("text/plain"));
RequestBody channelId = RequestBody.create(MediaType.parse("text/plain"), playlistParams.getVideoChannelId()); RequestBody channelId = RequestBody.create(playlistParams.getVideoChannelId(), MediaType.parse("text/plain"));
if (apiAction == PlaylistsVM.action.CREATE_PLAYLIST) { if (apiAction == PlaylistsVM.action.CREATE_PLAYLIST) {
Call<VideoPlaylistData.VideoPlaylistCreation> stringCall = peertubeService.addPlaylist(getToken(), displayName, description, playlistParams.getPrivacy(), channelId, body); Call<VideoPlaylistData.VideoPlaylistCreation> stringCall = peertubeService.addPlaylist(getToken(), displayName, description, playlistParams.getPrivacy(), channelId, bodyThumbnail);
Response<VideoPlaylistData.VideoPlaylistCreation> response = stringCall.execute(); Response<VideoPlaylistData.VideoPlaylistCreation> response = stringCall.execute();
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
apiResponse.setActionReturn(response.body().getVideoPlaylist().getId()); apiResponse.setActionReturn(response.body().getVideoPlaylist().getId());
@ -1116,7 +1478,7 @@ public class RetrofitPeertubeAPI {
} }
} else if (apiAction == PlaylistsVM.action.UPDATE_PLAYLIST) { } else if (apiAction == PlaylistsVM.action.UPDATE_PLAYLIST) {
Call<String> stringCall = peertubeService.updatePlaylist(getToken(), playlistId, displayName, description, playlistParams.getPrivacy(), channelId, body); Call<String> stringCall = peertubeService.updatePlaylist(getToken(), playlistId, displayName, description, playlistParams.getPrivacy(), channelId, bodyThumbnail);
Response<String> response = stringCall.execute(); Response<String> response = stringCall.execute();
if (response.isSuccessful()) { if (response.isSuccessful()) {
apiResponse.setActionReturn(response.body()); apiResponse.setActionReturn(response.body());
@ -1381,10 +1743,10 @@ public class RetrofitPeertubeAPI {
* @param id String id * @param id String id
* @return APIResponse * @return APIResponse
*/ */
public APIResponse getVideos(String id, boolean myVideo) { public APIResponse getVideos(String id, boolean myVideo, boolean canUseToken) {
PeertubeService peertubeService = init(); PeertubeService peertubeService = init();
Call<VideoData.Video> video; Call<VideoData.Video> video;
if (myVideo) { if (myVideo || canUseToken) {
video = peertubeService.getMyVideo(getToken(), id); video = peertubeService.getMyVideo(getToken(), id);
} else { } else {
video = peertubeService.getVideo(id); video = peertubeService.getVideo(id);
@ -1392,19 +1754,49 @@ public class RetrofitPeertubeAPI {
APIResponse apiResponse = new APIResponse(); APIResponse apiResponse = new APIResponse();
try { try {
Response<VideoData.Video> response = video.execute(); Response<VideoData.Video> response = video.execute();
if (response.isSuccessful()) { if (response.isSuccessful()) {
List<VideoData.Video> videos = new ArrayList<>(); List<VideoData.Video> videos = new ArrayList<>();
videos.add(response.body()); videos.add(response.body());
apiResponse.setPeertubes(videos); apiResponse.setPeertubes(videos);
} else { } else {
Error error = new Error();
error.setStatusCode(response.code());
if (response.errorBody() != null) { if (response.errorBody() != null) {
error.setError(response.errorBody().string());
String error = response.errorBody().string();
if (error.contains("originUrl")) {
try {
JSONObject jsonObject = new JSONObject(error);
List<VideoData.Video> videos = new ArrayList<>();
VideoData.Video videoRedirect = new VideoData.Video();
videoRedirect.setErrorCode(jsonObject.getInt("errorCode"));
videoRedirect.setOriginUrl(jsonObject.getString("originUrl"));
videos.add(videoRedirect);
apiResponse.setPeertubes(videos);
} catch (JSONException e) {
e.printStackTrace();
}
} else if (error.contains("error")) {
try {
JSONObject jsonObject = new JSONObject(error);
List<VideoData.Video> videos = new ArrayList<>();
VideoData.Video videoErrorMessage = new VideoData.Video();
videoErrorMessage.setErrorMessage(jsonObject.getString("error"));
videos.add(videoErrorMessage);
apiResponse.setPeertubes(videos);
} catch (JSONException e) {
e.printStackTrace();
}
}
} else { } else {
error.setError(_context.getString(R.string.toast_error)); Error error = new Error();
error.setStatusCode(response.code());
if (response.errorBody() != null) {
error.setError(response.errorBody().string());
} else {
error.setError(_context.getString(R.string.toast_error));
}
} }
} }
} catch (IOException e) { } catch (IOException e) {
Error error = new Error(); Error error = new Error();

View File

@ -1,9 +1,12 @@
package app.fedilab.fedilabtube.client.data; package app.fedilab.fedilabtube.client.data;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -239,5 +242,143 @@ public class InstanceData {
} }
} }
public static class InstanceInfo {
@SerializedName("instance")
private AboutInstance instance;
public AboutInstance getInstance() {
return instance;
}
public void setInstance(AboutInstance instance) {
this.instance = instance;
}
}
public static class AboutInstance implements Parcelable, Serializable {
public static final Creator<AboutInstance> CREATOR = new Creator<AboutInstance>() {
@Override
public AboutInstance createFromParcel(Parcel in) {
return new AboutInstance(in);
}
@Override
public AboutInstance[] newArray(int size) {
return new AboutInstance[size];
}
};
@SerializedName("name")
private String name;
@SerializedName("shortDescription")
private String shortDescription;
@SerializedName("description")
private String description;
@SerializedName("terms")
private String terms;
private String host;
public AboutInstance() {
}
protected AboutInstance(Parcel in) {
name = in.readString();
shortDescription = in.readString();
description = in.readString();
terms = in.readString();
host = in.readString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTerms() {
return terms;
}
public void setTerms(String terms) {
this.terms = terms;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(shortDescription);
parcel.writeString(description);
parcel.writeString(terms);
parcel.writeString(host);
}
}
public static class InstanceConfig {
@SerializedName("user")
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
public static class User {
@SerializedName("videoQuota")
private long videoQuota;
@SerializedName("videoQuotaDaily")
private long videoQuotaDaily;
public long getVideoQuota() {
return videoQuota;
}
public void setVideoQuota(long videoQuota) {
this.videoQuota = videoQuota;
}
public long getVideoQuotaDaily() {
return videoQuotaDaily;
}
public void setVideoQuotaDaily(long videoQuotaDaily) {
this.videoQuotaDaily = videoQuotaDaily;
}
}
} }

View File

@ -43,6 +43,7 @@ public class VideoData {
@SerializedName("data") @SerializedName("data")
public List<Video> data; public List<Video> data;
public static class Video implements Parcelable { public static class Video implements Parcelable {
public static final Creator<Video> CREATOR = new Creator<Video>() { public static final Creator<Video> CREATOR = new Creator<Video>() {
@Override @Override
@ -121,6 +122,8 @@ public class VideoData {
private List<String> trackerUrls; private List<String> trackerUrls;
@SerializedName("updatedAt") @SerializedName("updatedAt")
private Date updatedAt; private Date updatedAt;
@SerializedName("userHistory")
private UserHistory userHistory;
@SerializedName("uuid") @SerializedName("uuid")
private String uuid; private String uuid;
@SerializedName("views") @SerializedName("views")
@ -128,6 +131,9 @@ public class VideoData {
@SerializedName("waitTranscoding") @SerializedName("waitTranscoding")
private boolean waitTranscoding; private boolean waitTranscoding;
private String myRating; private String myRating;
private String originUrl;
private int errorCode;
private String errorMessage;
//Dedicated to overview videos to reuse the logic of videos //Dedicated to overview videos to reuse the logic of videos
private boolean hasTitle = false; private boolean hasTitle = false;
private String title; private String title;
@ -178,6 +184,7 @@ public class VideoData {
this.trackerUrls = in.createStringArrayList(); this.trackerUrls = in.createStringArrayList();
long tmpUpdatedAt = in.readLong(); long tmpUpdatedAt = in.readLong();
this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt);
this.userHistory = in.readParcelable(UserHistory.class.getClassLoader());
this.uuid = in.readString(); this.uuid = in.readString();
this.views = in.readInt(); this.views = in.readInt();
this.waitTranscoding = in.readByte() != 0; this.waitTranscoding = in.readByte() != 0;
@ -186,27 +193,29 @@ public class VideoData {
public String getFileUrl(String resolution, Context context) { public String getFileUrl(String resolution, Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean streamService = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL) == Helper.VIDEO_MODE_STREAMING; int mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
if (files != null && files.size() > 0) { if (files != null && files.size() > 0) {
if (resolution != null) { if (resolution != null) {
for (File file : files) { for (File file : files) {
if (file.getResolutions().getLabel().compareTo(resolution) == 0) { if (file.getResolutions().getLabel().compareTo(resolution) == 0) {
if (streamService) { if (mode == Helper.VIDEO_MODE_MAGNET) {
return file.getMagnetUri(); return file.getMagnetUri();
} else if (mode == Helper.VIDEO_MODE_TORRENT) {
return file.getTorrentUrl();
} else { } else {
return file.getFileUrl(); return file.getFileUrl();
} }
} }
} }
} }
File file = Helper.defaultFile(context, files); File file = Helper.defaultFile(context, files);
if (file != null) { if (file != null) {
if (streamService) { if (mode == Helper.VIDEO_MODE_MAGNET) {
return file.getMagnetUri(); return file.getMagnetUri();
} else if (mode == Helper.VIDEO_MODE_TORRENT) {
return file.getTorrentUrl();
} else { } else {
return file.getFileUrl(); return file.getFileUrl();
} }
} else { } else {
return null; return null;
@ -536,6 +545,22 @@ public class VideoData {
this.waitTranscoding = waitTranscoding; this.waitTranscoding = waitTranscoding;
} }
public String getOriginUrl() {
return originUrl;
}
public void setOriginUrl(String originUrl) {
this.originUrl = originUrl;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getMyRating() { public String getMyRating() {
return myRating; return myRating;
} }
@ -576,6 +601,22 @@ public class VideoData {
this.playlistExists = playlistExists; this.playlistExists = playlistExists;
} }
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public UserHistory getUserHistory() {
return userHistory;
}
public void setUserHistory(UserHistory userHistory) {
this.userHistory = userHistory;
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
@ -616,6 +657,7 @@ public class VideoData {
dest.writeString(this.thumbnailPath); dest.writeString(this.thumbnailPath);
dest.writeStringList(this.trackerUrls); dest.writeStringList(this.trackerUrls);
dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1);
dest.writeParcelable(this.userHistory, flags);
dest.writeString(this.uuid); dest.writeString(this.uuid);
dest.writeInt(this.views); dest.writeInt(this.views);
dest.writeByte(this.waitTranscoding ? (byte) 1 : (byte) 0); dest.writeByte(this.waitTranscoding ? (byte) 1 : (byte) 0);
@ -683,4 +725,136 @@ public class VideoData {
} }
public static class UserHistory implements Parcelable {
public static final Creator<UserHistory> CREATOR = new Creator<UserHistory>() {
@Override
public UserHistory createFromParcel(Parcel in) {
return new UserHistory(in);
}
@Override
public UserHistory[] newArray(int size) {
return new UserHistory[size];
}
};
@SerializedName("currentTime")
long currentTime;
public UserHistory() {
}
protected UserHistory(Parcel in) {
this.currentTime = in.readLong();
}
public long getCurrentTime() {
return currentTime;
}
public void setCurrentTime(long currentTime) {
this.currentTime = currentTime;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(currentTime);
}
}
public static class Description {
@SerializedName("description")
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public static class VideoExport implements Parcelable {
public static final Creator<VideoExport> CREATOR = new Creator<VideoExport>() {
@Override
public VideoExport createFromParcel(Parcel in) {
return new VideoExport(in);
}
@Override
public VideoExport[] newArray(int size) {
return new VideoExport[size];
}
};
private int id;
private String uuid;
private Video videoData;
private int playlistDBid;
public VideoExport() {
}
protected VideoExport(Parcel in) {
id = in.readInt();
uuid = in.readString();
videoData = in.readParcelable(Video.class.getClassLoader());
playlistDBid = in.readInt();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public Video getVideoData() {
return videoData;
}
public void setVideoData(Video videoData) {
this.videoData = videoData;
}
public int getPlaylistDBid() {
return playlistDBid;
}
public void setPlaylistDBid(int playlistDBid) {
this.playlistDBid = playlistDBid;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(uuid);
parcel.writeParcelable(videoData, i);
parcel.writeInt(playlistDBid);
}
}
} }

View File

@ -15,11 +15,15 @@ package app.fedilab.fedilabtube.client.data;
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.List; import java.util.List;
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public class VideoPlaylistData { public class VideoPlaylistData {
@ -155,4 +159,90 @@ public class VideoPlaylistData {
this.uuid = uuid; this.uuid = uuid;
} }
} }
public static class VideoPlaylistExport implements Parcelable {
public static final Creator<VideoPlaylistExport> CREATOR = new Creator<VideoPlaylistExport>() {
@Override
public VideoPlaylistExport createFromParcel(Parcel in) {
return new VideoPlaylistExport(in);
}
@Override
public VideoPlaylistExport[] newArray(int size) {
return new VideoPlaylistExport[size];
}
};
private long playlistDBkey;
private String acct;
private String uuid;
private PlaylistData.Playlist playlist;
private List<VideoPlaylistData.VideoPlaylist> videos;
public VideoPlaylistExport() {
}
protected VideoPlaylistExport(Parcel in) {
playlistDBkey = in.readLong();
acct = in.readString();
uuid = in.readString();
playlist = in.readParcelable(PlaylistData.Playlist.class.getClassLoader());
in.readList(this.videos, VideoPlaylistData.VideoPlaylist.class.getClassLoader());
}
public String getAcct() {
return acct;
}
public void setAcct(String acct) {
this.acct = acct;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public PlaylistData.Playlist getPlaylist() {
return playlist;
}
public void setPlaylist(PlaylistData.Playlist playlist) {
this.playlist = playlist;
}
public long getPlaylistDBkey() {
return playlistDBkey;
}
public void setPlaylistDBkey(long playlistDBkey) {
this.playlistDBkey = playlistDBkey;
}
public List<VideoPlaylistData.VideoPlaylist> getVideos() {
return videos;
}
public void setVideos(List<VideoPlaylistData.VideoPlaylist> videos) {
this.videos = videos;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(playlistDBkey);
parcel.writeString(acct);
parcel.writeString(uuid);
parcel.writeParcelable(playlist, i);
parcel.writeList(videos);
}
}
} }

View File

@ -1,11 +1,25 @@
package app.fedilab.fedilabtube.client.entities; package app.fedilab.fedilabtube.client.entities;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public class File { public class File implements Parcelable {
public static final Parcelable.Creator<File> CREATOR = new Parcelable.Creator<File>() {
@Override
public File createFromParcel(Parcel source) {
return new File(source);
}
@Override
public File[] newArray(int size) {
return new File[size];
}
};
@SerializedName("fileDownloadUrl") @SerializedName("fileDownloadUrl")
private String fileDownloadUrl; private String fileDownloadUrl;
@SerializedName("fileUrl") @SerializedName("fileUrl")
@ -25,6 +39,21 @@ public class File {
@SerializedName("torrentUrl") @SerializedName("torrentUrl")
private String torrentUrl; private String torrentUrl;
public File() {
}
protected File(Parcel in) {
this.fileDownloadUrl = in.readString();
this.fileUrl = in.readString();
this.fps = in.readInt();
this.magnetUri = in.readString();
this.metadataUrl = in.readString();
this.resolutions = in.readParcelable(Item.class.getClassLoader());
this.size = in.readLong();
this.torrentDownloadUrl = in.readString();
this.torrentUrl = in.readString();
}
public String getFileDownloadUrl() { public String getFileDownloadUrl() {
return fileDownloadUrl; return fileDownloadUrl;
} }
@ -96,4 +125,22 @@ public class File {
public void setTorrentUrl(String torrentUrl) { public void setTorrentUrl(String torrentUrl) {
this.torrentUrl = torrentUrl; this.torrentUrl = torrentUrl;
} }
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.fileDownloadUrl);
dest.writeString(this.fileUrl);
dest.writeInt(this.fps);
dest.writeString(this.magnetUri);
dest.writeString(this.metadataUrl);
dest.writeParcelable(this.resolutions, flags);
dest.writeLong(this.size);
dest.writeString(this.torrentDownloadUrl);
dest.writeString(this.torrentUrl);
}
} }

View File

@ -0,0 +1,92 @@
package app.fedilab.fedilabtube.client.entities;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
@SuppressWarnings({"unused", "RedundantSuppression"})
public class MenuItemView {
private int id;
private String strId;
private String label;
private boolean selected;
public MenuItemView() {
}
public MenuItemView(int id, String label) {
this.id = id;
this.label = label;
selected = false;
}
public MenuItemView(int id, String label, boolean selected) {
this.id = id;
this.label = label;
this.selected = selected;
}
public MenuItemView(String strId, String label, boolean selected) {
this.strId = strId;
this.label = label;
this.selected = selected;
}
public MenuItemView(String strId, String label) {
this.strId = strId;
this.label = label;
this.selected = false;
}
public MenuItemView(int id, String strId, String label, boolean selected) {
this.id = id;
this.strId = strId;
this.label = label;
this.selected = selected;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public String getStrId() {
return strId;
}
public void setStrId(String strId) {
this.strId = strId;
}
}

View File

@ -14,13 +14,27 @@ package app.fedilab.fedilabtube.client.entities;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.List; import java.util.List;
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public class StreamingPlaylists { public class StreamingPlaylists implements Parcelable {
public static final Creator<StreamingPlaylists> CREATOR = new Creator<StreamingPlaylists>() {
@Override
public StreamingPlaylists createFromParcel(Parcel in) {
return new StreamingPlaylists(in);
}
@Override
public StreamingPlaylists[] newArray(int size) {
return new StreamingPlaylists[size];
}
};
@SerializedName("id") @SerializedName("id")
private String id; private String id;
@SerializedName("type") @SerializedName("type")
@ -34,6 +48,15 @@ public class StreamingPlaylists {
@SerializedName("redundancies") @SerializedName("redundancies")
private List<Redundancies> redundancies; private List<Redundancies> redundancies;
protected StreamingPlaylists(Parcel in) {
id = in.readString();
type = in.readInt();
playlistUrl = in.readString();
segmentsSha256Url = in.readString();
files = in.createTypedArrayList(File.CREATOR);
redundancies = in.createTypedArrayList(Redundancies.CREATOR);
}
public String getId() { public String getId() {
return id; return id;
} }
@ -82,10 +105,41 @@ public class StreamingPlaylists {
this.redundancies = redundancies; this.redundancies = redundancies;
} }
public static class Redundancies { @Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(id);
parcel.writeInt(type);
parcel.writeString(playlistUrl);
parcel.writeString(segmentsSha256Url);
parcel.writeTypedList(files);
parcel.writeTypedList(redundancies);
}
public static class Redundancies implements Parcelable {
public static final Creator<Redundancies> CREATOR = new Creator<Redundancies>() {
@Override
public Redundancies createFromParcel(Parcel in) {
return new Redundancies(in);
}
@Override
public Redundancies[] newArray(int size) {
return new Redundancies[size];
}
};
@SerializedName("baseUrl") @SerializedName("baseUrl")
private String baseUrl; private String baseUrl;
protected Redundancies(Parcel in) {
baseUrl = in.readString();
}
public String getBaseUrl() { public String getBaseUrl() {
return baseUrl; return baseUrl;
} }
@ -93,5 +147,15 @@ public class StreamingPlaylists {
public void setBaseUrl(String baseUrl) { public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
} }
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(baseUrl);
}
} }
} }

View File

@ -31,6 +31,8 @@ public class UserMe {
private boolean autoPlayNextVideo; private boolean autoPlayNextVideo;
@SerializedName("autoPlayNextVideoPlaylist") @SerializedName("autoPlayNextVideoPlaylist")
private boolean autoPlayNextVideoPlaylist; private boolean autoPlayNextVideoPlaylist;
@SerializedName("autoPlayVideo")
private boolean autoPlayVideo;
@SerializedName("blocked") @SerializedName("blocked")
private boolean blocked; private boolean blocked;
@SerializedName("blockedReason") @SerializedName("blockedReason")
@ -64,9 +66,9 @@ public class UserMe {
@SerializedName("videoLanguages") @SerializedName("videoLanguages")
private List<String> videoLanguages; private List<String> videoLanguages;
@SerializedName("videoQuota") @SerializedName("videoQuota")
private String videoQuota; private long videoQuota;
@SerializedName("videoQuotaDaily") @SerializedName("videoQuotaDaily")
private String videoQuotaDaily; private long videoQuotaDaily;
@SerializedName("videosHistoryEnabled") @SerializedName("videosHistoryEnabled")
private boolean videosHistoryEnabled; private boolean videosHistoryEnabled;
@SerializedName("webTorrentEnabled") @SerializedName("webTorrentEnabled")
@ -224,19 +226,19 @@ public class UserMe {
this.videoLanguages = videoLanguages; this.videoLanguages = videoLanguages;
} }
public String getVideoQuota() { public long getVideoQuota() {
return videoQuota; return videoQuota;
} }
public void setVideoQuota(String videoQuota) { public void setVideoQuota(long videoQuota) {
this.videoQuota = videoQuota; this.videoQuota = videoQuota;
} }
public String getVideoQuotaDaily() { public long getVideoQuotaDaily() {
return videoQuotaDaily; return videoQuotaDaily;
} }
public void setVideoQuotaDaily(String videoQuotaDaily) { public void setVideoQuotaDaily(long videoQuotaDaily) {
this.videoQuotaDaily = videoQuotaDaily; this.videoQuotaDaily = videoQuotaDaily;
} }
@ -255,4 +257,49 @@ public class UserMe {
public void setWebTorrentEnabled(boolean webTorrentEnabled) { public void setWebTorrentEnabled(boolean webTorrentEnabled) {
this.webTorrentEnabled = webTorrentEnabled; this.webTorrentEnabled = webTorrentEnabled;
} }
public boolean isAutoPlayVideo() {
return autoPlayVideo;
}
public void setAutoPlayVideo(boolean autoPlayVideo) {
this.autoPlayVideo = autoPlayVideo;
}
public static class AvatarResponse {
@SerializedName("avatar")
private Avatar avatar;
public Avatar getAvatar() {
return avatar;
}
public void setAvatar(Avatar avatar) {
this.avatar = avatar;
}
}
public static class VideoQuota {
@SerializedName("videoQuotaUsed")
private long videoQuotaUsed;
@SerializedName("videoQuotaUsedDaily")
private long videoQuotaUsedDaily;
public long getVideoQuotaUsed() {
return videoQuotaUsed;
}
public void setVideoQuotaUsed(long videoQuotaUsed) {
this.videoQuotaUsed = videoQuotaUsed;
}
public long getVideoQuotaUsedDaily() {
return videoQuotaUsedDaily;
}
public void setVideoQuotaUsedDaily(long videoQuotaUsedDaily) {
this.videoQuotaUsedDaily = videoQuotaUsedDaily;
}
}
} }

View File

@ -0,0 +1,144 @@
package app.fedilab.fedilabtube.client.entities;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.net.Uri;
import java.util.List;
@SuppressWarnings({"unused", "RedundantSuppression"})
public class UserSettings {
private Boolean videosHistoryEnabled;
private Boolean autoPlayVideo;
private Boolean webTorrentEnabled;
private Boolean autoPlayNextVideo;
private List<String> videoLanguages;
private String description;
private String displayName;
private Uri avatarfile;
private String fileName;
private NotificationSettings notificationSettings;
private String nsfwPolicy;
public Boolean isVideosHistoryEnabled() {
return videosHistoryEnabled;
}
public Boolean isAutoPlayVideo() {
return autoPlayVideo;
}
public Boolean isWebTorrentEnabled() {
return webTorrentEnabled;
}
public List<String> getVideoLanguages() {
return videoLanguages;
}
public void setVideoLanguages(List<String> videoLanguages) {
this.videoLanguages = videoLanguages;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public Uri getAvatarfile() {
return avatarfile;
}
public void setAvatarfile(Uri avatarfile) {
this.avatarfile = avatarfile;
}
public Boolean getVideosHistoryEnabled() {
return videosHistoryEnabled;
}
public void setVideosHistoryEnabled(Boolean videosHistoryEnabled) {
this.videosHistoryEnabled = videosHistoryEnabled;
}
public Boolean getAutoPlayVideo() {
return autoPlayVideo;
}
public void setAutoPlayVideo(Boolean autoPlayVideo) {
this.autoPlayVideo = autoPlayVideo;
}
public Boolean getWebTorrentEnabled() {
return webTorrentEnabled;
}
public void setWebTorrentEnabled(Boolean webTorrentEnabled) {
this.webTorrentEnabled = webTorrentEnabled;
}
public Boolean isAutoPlayNextVideo() {
return autoPlayNextVideo;
}
public Boolean getAutoPlayNextVideo() {
return autoPlayNextVideo;
}
public void setAutoPlayNextVideo(Boolean autoPlayNextVideo) {
this.autoPlayNextVideo = autoPlayNextVideo;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
if (fileName == null) {
this.fileName = "avatar.png";
} else {
this.fileName = fileName;
}
}
public NotificationSettings getNotificationSettings() {
return notificationSettings;
}
public void setNotificationSettings(NotificationSettings notificationSettings) {
this.notificationSettings = notificationSettings;
}
public String getNsfwPolicy() {
return nsfwPolicy;
}
public void setNsfwPolicy(String nsfwPolicy) {
this.nsfwPolicy = nsfwPolicy;
}
}

View File

@ -14,18 +14,38 @@ package app.fedilab.fedilabtube.client.entities;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.Date; import java.util.Date;
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public class ViewsPerDay { public class ViewsPerDay implements Parcelable {
public static final Creator<ViewsPerDay> CREATOR = new Creator<ViewsPerDay>() {
@Override
public ViewsPerDay createFromParcel(Parcel in) {
return new ViewsPerDay(in);
}
@Override
public ViewsPerDay[] newArray(int size) {
return new ViewsPerDay[size];
}
};
@SerializedName("date") @SerializedName("date")
private Date date; private Date date;
@SerializedName("views") @SerializedName("views")
private int views; private int views;
protected ViewsPerDay(Parcel in) {
long tmpDate = in.readLong();
this.date = tmpDate == -1 ? null : new Date(tmpDate);
views = in.readInt();
}
public Date getDate() { public Date getDate() {
return date; return date;
} }
@ -41,4 +61,15 @@ public class ViewsPerDay {
public void setViews(int views) { public void setViews(int views) {
this.views = views; this.views = views;
} }
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(this.date != null ? this.date.getTime() : -1);
parcel.writeInt(views);
}
} }

View File

@ -0,0 +1,160 @@
package app.fedilab.fedilabtube.drawer;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.InstanceData;
import app.fedilab.fedilabtube.databinding.DrawerAboutInstanceBinding;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.sqlite.StoredInstanceDAO;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY;
public class AboutInstanceAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<InstanceData.AboutInstance> aboutInstances;
public AllInstancesRemoved allInstancesRemoved;
private Context context;
public AboutInstanceAdapter(List<InstanceData.AboutInstance> aboutInstances) {
this.aboutInstances = aboutInstances;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return aboutInstances.size();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
DrawerAboutInstanceBinding itemBinding = DrawerAboutInstanceBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding);
}
@SuppressLint("ApplySharedPref")
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) {
context = viewHolder.itemView.getContext();
final ViewHolder holder = (ViewHolder) viewHolder;
final InstanceData.AboutInstance aboutInstance = aboutInstances.get(i);
holder.binding.aboutInstanceHost.setText(aboutInstance.getHost());
SpannableString spannableString;
if (aboutInstance.getShortDescription() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
spannableString = new SpannableString(Html.fromHtml(aboutInstance.getShortDescription(), FROM_HTML_MODE_LEGACY));
else
spannableString = new SpannableString(Html.fromHtml(aboutInstance.getShortDescription()));
holder.binding.aboutInstanceDescription.setText(spannableString, TextView.BufferType.SPANNABLE);
}
holder.binding.aboutInstanceName.setText(aboutInstance.getName());
holder.binding.instanceContainer.setOnClickListener(v -> {
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_INSTANCE, aboutInstance.getHost());
editor.commit();
Helper.logoutNoRemoval((Activity) context);
});
holder.binding.instanceMore.setOnClickListener(v -> {
PopupMenu popup = new PopupMenu(context, holder.binding.instanceMore);
popup.getMenuInflater()
.inflate(R.menu.instance_menu, popup.getMenu());
popup.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.action_delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.delete_instance);
builder.setMessage(R.string.delete_instance_confirm);
builder.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(R.string.delete, (dialog, which) -> {
new Thread(() -> {
SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new StoredInstanceDAO(context, db).removeInstance(aboutInstance.getHost());
aboutInstances.remove(aboutInstance);
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
notifyItemRemoved(i);
if (aboutInstances.size() == 0) {
allInstancesRemoved.onAllInstancesRemoved();
}
};
mainHandler.post(myRunnable);
}).start();
dialog.dismiss();
})
.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
.show();
}
return true;
});
popup.show();
});
}
public interface AllInstancesRemoved {
void onAllInstancesRemoved();
}
static class ViewHolder extends RecyclerView.ViewHolder {
DrawerAboutInstanceBinding binding;
ViewHolder(DrawerAboutInstanceBinding itemView) {
super(itemView.getRoot());
binding = itemView;
}
}
}

View File

@ -19,19 +19,13 @@ import android.graphics.Color;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import java.util.List; import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.ChannelData; import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.databinding.DrawerHorizontalAccountBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
@ -50,8 +44,8 @@ public class AccountsHorizontalListAdapter extends RecyclerView.Adapter<Recycler
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext(); context = parent.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context); DrawerHorizontalAccountBinding itemBinding = DrawerHorizontalAccountBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(layoutInflater.inflate(R.layout.drawer_horizontal_account, parent, false)); return new ViewHolder(itemBinding);
} }
@Override @Override
@ -60,17 +54,17 @@ public class AccountsHorizontalListAdapter extends RecyclerView.Adapter<Recycler
final ChannelData.Channel channel = channels.get(position); final ChannelData.Channel channel = channels.get(position);
if (channel.getDisplayName() != null && !channel.getDisplayName().trim().equals("")) if (channel.getDisplayName() != null && !channel.getDisplayName().trim().equals(""))
holder.account_dn.setText(channel.getDisplayName()); holder.binding.accountDn.setText(channel.getDisplayName());
else else
holder.account_dn.setText(channel.getName().replace("@", "")); holder.binding.accountDn.setText(channel.getName().replace("@", ""));
//Profile picture //Profile picture
Helper.loadGiF(context, channel.getAvatar() != null ? channel.getAvatar().getPath() : null, holder.account_pp, 270); Helper.loadGiF(context, channel.getAvatar() != null ? channel.getAvatar().getPath() : null, holder.binding.accountPp, 270);
if (channel.isSelected()) { if (channel.isSelected()) {
holder.main_container.setBackgroundColor(ColorUtils.setAlphaComponent(ContextCompat.getColor(context, Helper.getColorAccent()), 50)); holder.binding.mainContainer.setBackgroundColor(ColorUtils.setAlphaComponent(ContextCompat.getColor(context, Helper.getColorAccent()), 50));
} else { } else {
holder.main_container.setBackgroundColor(Color.TRANSPARENT); holder.binding.mainContainer.setBackgroundColor(Color.TRANSPARENT);
} }
} }
@ -87,27 +81,24 @@ public class AccountsHorizontalListAdapter extends RecyclerView.Adapter<Recycler
public interface EventListener { public interface EventListener {
void click(String forAccount); void click(ChannelData.Channel channel);
} }
private class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView account_pp; DrawerHorizontalAccountBinding binding;
TextView account_dn;
LinearLayout main_container; ViewHolder(DrawerHorizontalAccountBinding itemView) {
super(itemView.getRoot());
binding = itemView;
itemView.getRoot().setOnClickListener(this);
ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
account_pp = itemView.findViewById(R.id.account_pp);
account_dn = itemView.findViewById(R.id.account_dn);
main_container = itemView.findViewById(R.id.main_container);
} }
@Override @Override
public void onClick(View v) { public void onClick(View v) {
ChannelData.Channel channel = channels.get(getAdapterPosition()); ChannelData.Channel channel = channels.get(getAdapterPosition());
listener.click(channel.getAcct()); listener.click(channel);
for (ChannelData.Channel acc : channels) { for (ChannelData.Channel acc : channels) {
acc.setSelected(acc.getId().compareTo(channel.getId()) == 0); acc.setSelected(acc.getId().compareTo(channel.getId()) == 0);
} }

View File

@ -130,7 +130,7 @@ public class AccountsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
} }
position++; position++;
} }
if (accounts.size() == 0) { if (accounts.size() == 0 && allAccountsRemoved != null) {
allAccountsRemoved.onAllAccountsRemoved(); allAccountsRemoved.onAllAccountsRemoved();
} }
} }

View File

@ -17,6 +17,7 @@ package app.fedilab.fedilabtube.drawer;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -45,15 +46,13 @@ import app.fedilab.fedilabtube.helper.Helper;
public class ChannelListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class ChannelListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<Channel> channels; private final List<Channel> channels;
private final boolean myChannel;
public AllChannelRemoved allChannelRemoved; public AllChannelRemoved allChannelRemoved;
public EditAlertDialog editAlertDialog; public EditAlertDialog editAlertDialog;
private Context context; private Context context;
public ChannelListAdapter(List<Channel> channels, boolean myChannel) { public ChannelListAdapter(List<Channel> channels) {
this.channels = channels; this.channels = channels;
this.myChannel = myChannel;
} }
@NonNull @NonNull
@ -77,7 +76,7 @@ public class ChannelListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
//Profile picture //Profile picture
Helper.loadGiF(context, channel.getAvatar() != null ? channel.getAvatar().getPath() : null, holder.account_pp); Helper.loadGiF(context, channel.getAvatar() != null ? channel.getAvatar().getPath() : null, holder.account_pp);
if (!this.myChannel) { if (!isMyChannel(channel)) {
holder.more_actions.setVisibility(View.GONE); holder.more_actions.setVisibility(View.GONE);
} }
holder.more_actions.setOnClickListener(view -> { holder.more_actions.setOnClickListener(view -> {
@ -132,6 +131,20 @@ public class ChannelListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
} }
private boolean isMyChannel(Channel channel) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String channeIdOwner = channel.getOwnerAccount().getId();
String channeInstanceOwner = channel.getOwnerAccount().getHost();
String instanceShar = sharedpreferences.getString(Helper.PREF_INSTANCE, null);
String userIdShar = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
if (channeIdOwner != null && channeInstanceOwner != null && instanceShar != null && userIdShar != null) {
return channeIdOwner.compareTo(userIdShar) == 0 && channeInstanceOwner.compareTo(instanceShar) == 0;
} else {
return false;
}
}
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
return position; return position;

View File

@ -34,14 +34,12 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@ -59,15 +57,15 @@ import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.CommentData.Comment; import app.fedilab.fedilabtube.client.data.CommentData.Comment;
import app.fedilab.fedilabtube.client.entities.Report; import app.fedilab.fedilabtube.client.entities.Report;
import app.fedilab.fedilabtube.databinding.DrawerCommentBinding;
import app.fedilab.fedilabtube.helper.CommentDecorationHelper;
import app.fedilab.fedilabtube.helper.EmojiHelper; import app.fedilab.fedilabtube.helper.EmojiHelper;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.PostActionsVM; import app.fedilab.fedilabtube.viewmodel.PostActionsVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import studio.carbonylgroup.textfieldboxes.ExtendedEditText;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPLY; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPLY;
import static app.fedilab.fedilabtube.helper.Helper.isLoggedIn;
public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@ -75,14 +73,18 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
private final List<Comment> comments; private final List<Comment> comments;
private final CommentListAdapter commentListAdapter; private final CommentListAdapter commentListAdapter;
private final boolean isThread;
public AllCommentRemoved allCommentRemoved; public AllCommentRemoved allCommentRemoved;
boolean isVideoOwner; boolean isVideoOwner;
private Context context; private Context context;
private final String instance;
public CommentListAdapter(List<Comment> comments, boolean isVideoOwner) { public CommentListAdapter(List<Comment> comments, boolean isVideoOwner, boolean isThread, String instance) {
this.comments = comments; this.comments = comments;
commentListAdapter = this; commentListAdapter = this;
this.isVideoOwner = isVideoOwner; this.isVideoOwner = isVideoOwner;
this.isThread = isThread;
this.instance = instance;
} }
@Override @Override
@ -101,10 +103,11 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext(); context = parent.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(this.context); DrawerCommentBinding itemBinding = DrawerCommentBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(layoutInflater.inflate(R.layout.drawer_comment, parent, false)); return new ViewHolder(itemBinding);
} }
@SuppressLint({"SetJavaScriptEnabled", "ClickableViewAccessibility"}) @SuppressLint({"SetJavaScriptEnabled", "ClickableViewAccessibility"})
@Override @Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) { public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) {
@ -118,10 +121,23 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
if (comment == null) if (comment == null)
return; return;
holder.main_container.setTag(i); holder.binding.mainContainer.setTag(i);
holder.more_actions.setOnClickListener(view -> {
PopupMenu popup = new PopupMenu(context, holder.more_actions); holder.binding.decorationContainer.removeAllViews();
if (comment.isReply()) {
int ident = CommentDecorationHelper.getIndentation(comment.getInReplyToCommentId(), comments);
for (int j = 0; j <= ident; j++) {
View view = new View(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(1, LinearLayout.LayoutParams.MATCH_PARENT);
params.setMargins((int) Helper.convertDpToPixel(5, context), 0, 0, 0);
view.setBackgroundResource(R.color.colorAccent);
view.setLayoutParams(params);
holder.binding.decorationContainer.addView(view, 0);
}
}
holder.binding.moreActions.setOnClickListener(view -> {
PopupMenu popup = new PopupMenu(context, holder.binding.moreActions);
popup.getMenuInflater() popup.getMenuInflater()
.inflate(R.menu.comment_menu, popup.getMenu()); .inflate(R.menu.comment_menu, popup.getMenu());
if (!Helper.isOwner(context, comment.getAccount())) { if (!Helper.isOwner(context, comment.getAccount())) {
@ -203,7 +219,7 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
}); });
popup.show(); popup.show();
}); });
holder.comment_content.setOnTouchListener((view, motionEvent) -> { holder.binding.commentContent.setOnTouchListener((view, motionEvent) -> {
if (motionEvent.getAction() == MotionEvent.ACTION_UP && !view.hasFocus()) { if (motionEvent.getAction() == MotionEvent.ACTION_UP && !view.hasFocus()) {
try { try {
view.requestFocus(); view.requestFocus();
@ -218,21 +234,22 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
commentSpan = Html.fromHtml(EmojiHelper.shortnameToUnicode(comment.getText()), Html.FROM_HTML_MODE_COMPACT); commentSpan = Html.fromHtml(EmojiHelper.shortnameToUnicode(comment.getText()), Html.FROM_HTML_MODE_COMPACT);
else else
commentSpan = Html.fromHtml(EmojiHelper.shortnameToUnicode(comment.getText())); commentSpan = Html.fromHtml(EmojiHelper.shortnameToUnicode(comment.getText()));
holder.comment_content.setText(commentSpan, TextView.BufferType.SPANNABLE); holder.binding.commentContent.setText(commentSpan, TextView.BufferType.SPANNABLE);
holder.comment_content.setMovementMethod(LinkMovementMethod.getInstance()); holder.binding.commentContent.setMovementMethod(LinkMovementMethod.getInstance());
holder.comment_account_displayname.setText(comment.getAccount().getDisplayName()); holder.binding.commentAccountDisplayname.setText(comment.getAccount().getDisplayName());
if (context instanceof PeertubeActivity && !comment.isReply()) {
holder.main_container.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment, i)); if (context instanceof PeertubeActivity && !isThread) {
holder.comment_content.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment, i)); holder.binding.mainContainer.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment));
holder.binding.commentContent.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment));
} }
if (comment.getTotalReplies() > 0) { if (comment.getTotalReplies() > 0) {
holder.number_of_replies.setVisibility(View.VISIBLE); holder.binding.numberOfReplies.setVisibility(View.VISIBLE);
holder.number_of_replies.setText(context.getResources().getQuantityString(R.plurals.number_of_replies, comment.getTotalReplies(), comment.getTotalReplies())); holder.binding.numberOfReplies.setText(context.getResources().getQuantityString(R.plurals.number_of_replies, comment.getTotalReplies(), comment.getTotalReplies()));
} else { } else {
holder.number_of_replies.setVisibility(View.GONE); holder.binding.numberOfReplies.setVisibility(View.GONE);
} }
if (comment.getAccount() != null) { if (comment.getAccount() != null) {
@ -248,15 +265,20 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
wordtoSpan.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, android.R.color.darker_gray)), matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); wordtoSpan.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, android.R.color.darker_gray)), matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
} }
} }
holder.comment_account_username.setText(wordtoSpan); holder.binding.commentAccountUsername.setText(wordtoSpan);
} }
holder.comment_date.setText(Helper.dateDiff(context, comment.getCreatedAt())); holder.binding.commentDate.setText(Helper.dateDiff(context, comment.getCreatedAt()));
String avatarUrl;
if (instance != null) {
avatarUrl = comment.getAccount().getAvatar() != null ? "https://" + instance + comment.getAccount().getAvatar().getPath() : null;
} else {
avatarUrl = comment.getAccount().getAvatar() != null ? comment.getAccount().getAvatar().getPath() : null;
}
Helper.loadGiF(context, avatarUrl, holder.binding.commentAccountProfile);
Helper.loadGiF(context, comment.getAccount().getAvatar() != null ? comment.getAccount().getAvatar().getPath() : null, holder.comment_account_profile); holder.binding.commentAccountProfile.setOnClickListener(v -> {
holder.comment_account_profile.setOnClickListener(v -> {
Bundle b = new Bundle(); Bundle b = new Bundle();
Intent intent = new Intent(context, ShowAccountActivity.class); Intent intent = new Intent(context, ShowAccountActivity.class);
b.putParcelable("account", comment.getAccount()); b.putParcelable("account", comment.getAccount());
@ -265,37 +287,17 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
context.startActivity(intent); context.startActivity(intent);
}); });
if (comment.isReply()) { if (comment.isReply()) {
holder.replyButton.setVisibility(View.VISIBLE); holder.binding.replyButton.setVisibility(View.VISIBLE);
} else { } else {
holder.replyButton.setVisibility(View.GONE); holder.binding.replyButton.setVisibility(View.GONE);
} }
if (comment.isReply() && comment.isReplyViewOpen()) { if (i == 0 && isThread) {
holder.write_comment_container_reply.setVisibility(View.VISIBLE); holder.binding.postReplyButton.setVisibility(View.VISIBLE);
} else { } else {
holder.write_comment_container_reply.setVisibility(View.GONE); holder.binding.postReplyButton.setVisibility(View.GONE);
} }
if (holder.add_comment_write_reply.getText() == null || holder.add_comment_write_reply.getText().toString().trim().length() == 0) { holder.binding.postReplyButton.setOnClickListener(v -> ((PeertubeActivity) context).openPostComment(comment, i));
holder.add_comment_write_reply.setText(String.format("@%s ", comment.getAccount().getAcct())); holder.binding.replyButton.setOnClickListener(v -> ((PeertubeActivity) context).openPostComment(comment, i));
holder.add_comment_write_reply.setSelection(holder.add_comment_write_reply.getText().length());
}
holder.replyButton.setOnClickListener(v -> {
comment.setReplyViewOpen(!comment.isReplyViewOpen());
notifyItemChanged(i);
});
holder.send_reply.setOnClickListener(null);
holder.send_reply.setOnClickListener(v -> {
if (isLoggedIn(context)) {
String commentView = holder.add_comment_write_reply.getText().toString();
if (commentView.trim().length() > 0) {
PostActionsVM viewModelComment = new ViewModelProvider((ViewModelStoreOwner) context).get(PostActionsVM.class);
viewModelComment.comment(REPLY, comment.getVideoId(), comment.getId(), commentView).observe((LifecycleOwner) context, apiResponse1 -> manageVIewPostActions(REPLY, (int) holder.main_container.getTag(), apiResponse1));
holder.add_comment_write_reply.setText("");
comment.setReplyViewOpen(false);
notifyItemChanged(i);
}
}
});
} }
public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, int i, APIResponse apiResponse) { public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, int i, APIResponse apiResponse) {
@ -356,42 +358,15 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
void onAllCommentRemoved(); void onAllCommentRemoved();
} }
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {
DrawerCommentBinding binding;
TextView comment_content; ViewHolder(DrawerCommentBinding itemView) {
TextView comment_account_username; super(itemView.getRoot());
TextView comment_account_displayname; binding = itemView;
ImageView comment_account_profile, send_reply;
TextView comment_date, replyButton;
LinearLayout main_container;
TextView more_actions, number_of_replies;
ExtendedEditText add_comment_write_reply;
ConstraintLayout write_comment_container_reply;
@SuppressLint("SetJavaScriptEnabled")
ViewHolder(View itemView) {
super(itemView);
comment_content = itemView.findViewById(R.id.comment_content);
comment_account_username = itemView.findViewById(R.id.comment_account_username);
comment_account_profile = itemView.findViewById(R.id.comment_account_profile);
comment_account_displayname = itemView.findViewById(R.id.comment_account_displayname);
comment_date = itemView.findViewById(R.id.comment_date);
main_container = itemView.findViewById(R.id.main_container);
more_actions = itemView.findViewById(R.id.more_actions);
number_of_replies = itemView.findViewById(R.id.number_of_replies);
add_comment_write_reply = itemView.findViewById(R.id.add_comment_write_reply);
send_reply = itemView.findViewById(R.id.send_reply);
replyButton = itemView.findViewById(R.id.replyButton);
write_comment_container_reply = itemView.findViewById(R.id.write_comment_container_reply);
} }
public View getView() {
return itemView;
}
} }
} }

View File

@ -38,7 +38,7 @@ import app.fedilab.fedilabtube.client.data.InstanceData.Instance;
import app.fedilab.fedilabtube.helper.RoundedBackgroundSpan; import app.fedilab.fedilabtube.helper.RoundedBackgroundSpan;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation; import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class InstanceAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class InstanceAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

View File

@ -0,0 +1,87 @@
package app.fedilab.fedilabtube.drawer;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import app.fedilab.fedilabtube.client.MenuItemVideo;
import app.fedilab.fedilabtube.databinding.DrawerMenuBinding;
public class MenuAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<MenuItemVideo> menuItemVideos;
public ItemClicked itemClicked;
public MenuAdapter(List<MenuItemVideo> menuItemVideos) {
this.menuItemVideos = menuItemVideos;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return menuItemVideos.size();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
DrawerMenuBinding itemBinding = DrawerMenuBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding);
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) {
final ViewHolder holder = (ViewHolder) viewHolder;
final MenuItemVideo menuItemVideo = menuItemVideos.get(i);
holder.binding.menuIcon.setImageResource(menuItemVideo.getIcon());
holder.binding.title.setText(menuItemVideo.getTitle());
holder.binding.itemMenuContainer.setOnClickListener(v -> itemClicked.onItemClicked(menuItemVideo.getAction()));
}
public interface ItemClicked {
void onItemClicked(MenuItemVideo.actionType actionType);
}
static class ViewHolder extends RecyclerView.ViewHolder {
DrawerMenuBinding binding;
ViewHolder(DrawerMenuBinding itemView) {
super(itemView.getRoot());
binding = itemView;
}
}
}

View File

@ -0,0 +1,89 @@
package app.fedilab.fedilabtube.drawer;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import app.fedilab.fedilabtube.client.MenuItemVideo;
import app.fedilab.fedilabtube.client.entities.MenuItemView;
import app.fedilab.fedilabtube.databinding.DrawerMenuItemBinding;
public class MenuItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<MenuItemView> items;
public ItemAction itemAction;
MenuItemVideo.actionType actionType;
public MenuItemAdapter(MenuItemVideo.actionType actionType, List<MenuItemView> items) {
this.items = items;
this.actionType = actionType;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return items.size();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
DrawerMenuItemBinding itemBinding = DrawerMenuItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding);
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) {
final ViewHolder holder = (ViewHolder) viewHolder;
final MenuItemView item = items.get(i);
holder.binding.title.setText(item.getLabel());
holder.binding.radio.setChecked(item.isSelected());
holder.binding.itemMenuContainer.setOnClickListener(v -> itemAction.which(actionType, item));
holder.binding.radio.setOnClickListener(v -> itemAction.which(actionType, item));
}
public interface ItemAction {
void which(MenuItemVideo.actionType actionType, MenuItemView item);
}
static class ViewHolder extends RecyclerView.ViewHolder {
DrawerMenuItemBinding binding;
ViewHolder(DrawerMenuItemBinding itemView) {
super(itemView.getRoot());
binding = itemView;
}
}
}

View File

@ -14,10 +14,12 @@ package app.fedilab.fedilabtube.drawer;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -25,9 +27,9 @@ import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
@ -35,6 +37,14 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner; import androidx.lifecycle.ViewModelStoreOwner;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -49,11 +59,13 @@ import app.fedilab.fedilabtube.client.data.PlaylistData;
import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.PlaylistExist; import app.fedilab.fedilabtube.client.entities.PlaylistExist;
import app.fedilab.fedilabtube.client.entities.Report; import app.fedilab.fedilabtube.client.entities.Report;
import app.fedilab.fedilabtube.databinding.DrawerPeertubeBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; import app.fedilab.fedilabtube.viewmodel.PlaylistsVM;
import app.fedilab.fedilabtube.viewmodel.PostActionsVM; import app.fedilab.fedilabtube.viewmodel.PostActionsVM;
import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import jp.wasabeef.glide.transformations.BlurTransformation;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.UNFOLLOW; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.UNFOLLOW;
@ -86,8 +98,8 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext(); context = parent.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context); DrawerPeertubeBinding itemBinding = DrawerPeertubeBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(layoutInflater.inflate(R.layout.drawer_peertube, parent, false)); return new ViewHolder(itemBinding);
} }
@Override @Override
@ -105,6 +117,7 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
assert userId != null; assert userId != null;
boolean videoInList = sharedpreferences.getBoolean(context.getString(R.string.set_video_in_list_choice), false);
boolean ownVideos; boolean ownVideos;
if (timelineType == TimelineVM.TimelineType.MY_VIDEOS) { if (timelineType == TimelineVM.TimelineType.MY_VIDEOS) {
@ -118,34 +131,43 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
instance = video.getAccount().getHost(); instance = video.getAccount().getHost();
} }
holder.peertube_account_name.setText(video.getChannel().getAcct()); holder.binding.peertubeAccountName.setText(video.getChannel().getAcct());
Helper.loadGiF(context, instance, video.getChannel().getAvatar() != null ? video.getChannel().getAvatar().getPath() : null, holder.peertube_profile); Helper.loadGiF(context, instance, video.getChannel().getAvatar() != null ? video.getChannel().getAvatar().getPath() : null, holder.binding.peertubeProfile);
holder.peertube_title.setText(video.getName()); holder.binding.peertubeTitle.setText(video.getName());
holder.peertube_duration.setText(Helper.secondsToString(video.getDuration())); holder.binding.peertubeDuration.setText(Helper.secondsToString(video.getDuration()));
holder.peertube_date.setText(String.format(" - %s", Helper.dateDiff(context, video.getCreatedAt()))); holder.binding.peertubeDate.setText(String.format(" - %s", Helper.dateDiff(context, video.getCreatedAt())));
holder.peertube_views.setText(context.getString(R.string.number_view_video, Helper.withSuffix(video.getViews()))); holder.binding.peertubeViews.setText(context.getString(R.string.number_view_video, Helper.withSuffix(video.getViews())));
Helper.loadGiF(context, instance, video.getThumbnailPath(), holder.peertube_video_image); boolean blur = sharedpreferences.getString(context.getString(R.string.set_video_sensitive_choice), Helper.BLUR).compareTo("blur") == 0 && video.isNsfw();
if (videoInList) {
Helper.loadGiF(context, instance, video.getThumbnailPath(), holder.binding.peertubeVideoImageSmall, blur);
holder.binding.peertubeVideoImageSmall.setVisibility(View.VISIBLE);
holder.binding.previewContainer.setVisibility(View.GONE);
} else {
loadImage(holder.binding.peertubeVideoImage, instance, video.getPreviewPath(), video.getThumbnailPath(), blur);
holder.binding.peertubeVideoImageSmall.setVisibility(View.GONE);
holder.binding.previewContainer.setVisibility(View.VISIBLE);
}
//For Overview Videos: boolean values for displaying title is managed in the fragment //For Overview Videos: boolean values for displaying title is managed in the fragment
if (video.isHasTitle()) { if (video.isHasTitle()) {
holder.header_title.setVisibility(View.VISIBLE); holder.binding.headerTitle.setVisibility(View.VISIBLE);
switch (video.getTitleType()) { switch (video.getTitleType()) {
case TAG: case TAG:
holder.header_title.setText(String.format("#%s", video.getTitle())); holder.binding.headerTitle.setText(String.format("#%s", video.getTitle()));
break; break;
case CHANNEL: case CHANNEL:
case CATEGORY: case CATEGORY:
holder.header_title.setText(String.format("%s", video.getTitle())); holder.binding.headerTitle.setText(String.format("%s", video.getTitle()));
break; break;
} }
} else { } else {
holder.header_title.setVisibility(View.GONE); holder.binding.headerTitle.setVisibility(View.GONE);
} }
if (!ownVideos) { if (!ownVideos) {
holder.peertube_profile.setOnClickListener(v -> { holder.binding.peertubeProfile.setOnClickListener(v -> {
Intent intent = new Intent(context, ShowChannelActivity.class); Intent intent = new Intent(context, ShowChannelActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putParcelable("channel", video.getChannel()); b.putParcelable("channel", video.getChannel());
@ -159,8 +181,8 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
} }
holder.more_actions.setOnClickListener(view -> { holder.binding.moreActions.setOnClickListener(view -> {
PopupMenu popup = new PopupMenu(context, holder.more_actions); PopupMenu popup = new PopupMenu(context, holder.binding.moreActions);
popup.getMenuInflater() popup.getMenuInflater()
.inflate(R.menu.video_drawer_menu, popup.getMenu()); .inflate(R.menu.video_drawer_menu, popup.getMenu());
if (timelineType == MY_VIDEOS) { if (timelineType == MY_VIDEOS) {
@ -245,7 +267,7 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
}); });
popup.show(); popup.show();
}); });
holder.bottom_container.setOnClickListener(v -> { holder.binding.bottomContainer.setOnClickListener(v -> {
Intent intent = new Intent(context, PeertubeActivity.class); Intent intent = new Intent(context, PeertubeActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putString("video_id", video.getId()); b.putString("video_id", video.getId());
@ -259,7 +281,7 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
intent.putExtras(b); intent.putExtras(b);
context.startActivity(intent); context.startActivity(intent);
}); });
holder.peertube_video_image.setOnClickListener(v -> { holder.binding.peertubeVideoImage.setOnClickListener(v -> {
Intent intent = new Intent(context, PeertubeActivity.class); Intent intent = new Intent(context, PeertubeActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putString("video_id", video.getId()); b.putString("video_id", video.getId());
@ -374,26 +396,74 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
Map<String, List<PlaylistExist>> getPlaylist(); Map<String, List<PlaylistExist>> getPlaylist();
} }
@SuppressLint("CheckResult")
private void loadImage(ImageView target, String instance, String urlPreview, String thumbnail, boolean blur) {
if (urlPreview == null || urlPreview.startsWith("null")) {
urlPreview = thumbnail;
}
if (instance != null) {
urlPreview = "https://" + instance + urlPreview;
thumbnail = "https://" + instance + thumbnail;
} else {
urlPreview = "https://" + Helper.getLiveInstance(context) + urlPreview;
thumbnail = "https://" + Helper.getLiveInstance(context) + thumbnail;
}
RequestBuilder<Drawable> requestBuilder = Glide.with(context)
.asDrawable();
if (blur) {
requestBuilder.apply(new RequestOptions().transform(new BlurTransformation(50, 3), new CenterCrop(), new RoundedCorners(10)));
} else {
requestBuilder.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)));
}
final Drawable[] initialResource = new Drawable[1];
String finalUrlPreview = urlPreview;
requestBuilder.load(thumbnail).into(
new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull final Drawable resource, Transition<? super Drawable> transition) {
target.setImageDrawable(resource);
initialResource[0] = resource;
RequestBuilder<Drawable> requestBuilder = Glide.with(context)
.asDrawable();
if (blur) {
requestBuilder.apply(new RequestOptions().transform(new BlurTransformation(50, 3), new CenterCrop(), new RoundedCorners(10)));
} else {
requestBuilder.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)));
}
requestBuilder.load(finalUrlPreview).into(
new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull final Drawable resource, Transition<? super Drawable> transition) {
target.setImageDrawable(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
target.setImageDrawable(initialResource[0]);
}
}
);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
}
);
}
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout main_container, bottom_container; DrawerPeertubeBinding binding;
ImageView peertube_profile, peertube_video_image;
TextView peertube_account_name, peertube_views, peertube_duration;
TextView peertube_title, peertube_date, header_title, more_actions;
public ViewHolder(@NonNull View itemView) { ViewHolder(DrawerPeertubeBinding itemView) {
super(itemView); super(itemView.getRoot());
peertube_account_name = itemView.findViewById(R.id.peertube_account_name); binding = itemView;
peertube_title = itemView.findViewById(R.id.peertube_title);
peertube_video_image = itemView.findViewById(R.id.peertube_video_image);
peertube_profile = itemView.findViewById(R.id.peertube_profile);
peertube_date = itemView.findViewById(R.id.peertube_date);
peertube_views = itemView.findViewById(R.id.peertube_views);
peertube_duration = itemView.findViewById(R.id.peertube_duration);
main_container = itemView.findViewById(R.id.main_container);
header_title = itemView.findViewById(R.id.header_title);
bottom_container = itemView.findViewById(R.id.bottom_container);
more_actions = itemView.findViewById(R.id.more_actions);
} }
} }

View File

@ -14,98 +14,114 @@ package app.fedilab.fedilabtube.drawer;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner; import androidx.lifecycle.ViewModelStoreOwner;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.FutureTarget;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import app.fedilab.fedilabtube.AllPlaylistsActivity; import app.fedilab.fedilabtube.AllPlaylistsActivity;
import app.fedilab.fedilabtube.BuildConfig;
import app.fedilab.fedilabtube.LocalPlaylistsActivity;
import app.fedilab.fedilabtube.MainActivity;
import app.fedilab.fedilabtube.PlaylistsActivity; import app.fedilab.fedilabtube.PlaylistsActivity;
import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist; import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist;
import app.fedilab.fedilabtube.client.data.VideoPlaylistData;
import app.fedilab.fedilabtube.databinding.DrawerPlaylistBinding;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.helper.NotificationHelper;
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
import app.fedilab.fedilabtube.sqlite.ManagePlaylistsDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; import app.fedilab.fedilabtube.viewmodel.PlaylistsVM;
import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.viewmodel.PlaylistsVM.action.GET_LIST_VIDEOS;
public class PlaylistAdapter extends BaseAdapter { public class PlaylistAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<Playlist> playlists; private final List<Playlist> playlists;
private final LayoutInflater layoutInflater; private final boolean locale;
private final Context context; public AllPlaylistRemoved allPlaylistRemoved;
private final RelativeLayout textviewNoAction; private Context context;
public PlaylistAdapter(Context context, List<Playlist> lists, RelativeLayout textviewNoAction) { public PlaylistAdapter(List<Playlist> lists, boolean locale) {
this.playlists = lists; this.playlists = lists;
layoutInflater = LayoutInflater.from(context); this.locale = locale;
this.context = context;
this.textviewNoAction = textviewNoAction;
} }
@NonNull
@Override @Override
public int getCount() { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return playlists.size(); context = parent.getContext();
DrawerPlaylistBinding itemBinding = DrawerPlaylistBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding);
} }
@SuppressLint({"SetJavaScriptEnabled", "ClickableViewAccessibility"})
@Override @Override
public Object getItem(int position) { public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int position) {
return playlists.get(position); context = viewHolder.itemView.getContext();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder = (ViewHolder) viewHolder;
final Playlist playlist = playlists.get(position); final Playlist playlist = playlists.get(position);
final ViewHolder holder; String imgUrl;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.drawer_playlist, parent, false); if (locale) {
holder = new ViewHolder(); imgUrl = "https://" + playlist.getOwnerAccount().getHost() + playlist.getThumbnailPath();
holder.preview_title = convertView.findViewById(R.id.preview_title);
holder.preview_visibility = convertView.findViewById(R.id.preview_visibility);
holder.preview_description = convertView.findViewById(R.id.preview_description);
holder.playlist_container = convertView.findViewById(R.id.playlist_container);
holder.preview_playlist = convertView.findViewById(R.id.preview_playlist);
holder.playlist_more = convertView.findViewById(R.id.playlist_more);
convertView.setTag(holder);
} else { } else {
holder = (ViewHolder) convertView.getTag(); imgUrl = playlist.getThumbnailPath();
} }
Helper.loadGiF(context, imgUrl, holder.binding.previewPlaylist);
Helper.loadGiF(context, playlist.getThumbnailPath(), holder.preview_playlist); holder.binding.previewTitle.setText(playlist.getDisplayName());
holder.preview_title.setText(playlist.getDisplayName());
if (playlist.getDescription() != null && playlist.getDescription().trim().compareTo("null") != 0 && playlist.getDescription().length() > 0) { if (playlist.getDescription() != null && playlist.getDescription().trim().compareTo("null") != 0 && playlist.getDescription().length() > 0) {
holder.preview_description.setText(playlist.getDescription()); holder.binding.previewDescription.setText(playlist.getDescription());
holder.preview_description.setVisibility(View.VISIBLE); holder.binding.previewDescription.setVisibility(View.VISIBLE);
} else { } else {
holder.preview_description.setVisibility(View.GONE); holder.binding.previewDescription.setVisibility(View.GONE);
} }
holder.preview_visibility.setText(playlist.getPrivacy().getLabel()); holder.binding.previewVisibility.setText(playlist.getPrivacy().getLabel());
holder.playlist_container.setOnClickListener(v -> { holder.binding.playlistContainer.setOnClickListener(v -> {
Intent intent = new Intent(context, PlaylistsActivity.class); Intent intent = new Intent(context, locale ? LocalPlaylistsActivity.class : PlaylistsActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putParcelable("playlist", playlist); b.putParcelable("playlist", playlist);
intent.putExtras(b); intent.putExtras(b);
@ -113,15 +129,22 @@ public class PlaylistAdapter extends BaseAdapter {
}); });
if (playlist.getDisplayName().compareTo("Watch later") == 0) { if (playlist.getDisplayName().compareTo("Watch later") == 0) {
holder.playlist_more.setVisibility(View.GONE); holder.binding.playlistMore.setVisibility(View.GONE);
} else { } else {
holder.playlist_more.setVisibility(View.VISIBLE); holder.binding.playlistMore.setVisibility(View.VISIBLE);
} }
holder.playlist_more.setOnClickListener(v -> { holder.binding.playlistMore.setOnClickListener(v -> {
PopupMenu popup = new PopupMenu(context, holder.playlist_more); PopupMenu popup = new PopupMenu(context, holder.binding.playlistMore);
popup.getMenuInflater() popup.getMenuInflater()
.inflate(R.menu.playlist_menu, popup.getMenu()); .inflate(R.menu.playlist_menu, popup.getMenu());
if (!BuildConfig.full_instances) {
popup.getMenu().findItem(R.id.action_export).setVisible(true);
}
if (locale) {
popup.getMenu().findItem(R.id.action_export).setVisible(false);
popup.getMenu().findItem(R.id.action_edit).setVisible(false);
}
popup.setOnMenuItemClickListener(item -> { popup.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId(); int itemId = item.getItemId();
if (itemId == R.id.action_delete) { if (itemId == R.id.action_delete) {
@ -132,11 +155,18 @@ public class PlaylistAdapter extends BaseAdapter {
.setPositiveButton(R.string.yes, (dialog, which) -> { .setPositiveButton(R.string.yes, (dialog, which) -> {
playlists.remove(playlist); playlists.remove(playlist);
notifyDataSetChanged(); notifyDataSetChanged();
PlaylistsVM viewModel = new ViewModelProvider((ViewModelStoreOwner) context).get(PlaylistsVM.class); if (!locale) {
viewModel.manage(PlaylistsVM.action.DELETE_PLAYLIST, playlist, null).observe((LifecycleOwner) context, apiResponse -> manageVIewPlaylists(PlaylistsVM.action.DELETE_PLAYLIST, apiResponse)); PlaylistsVM viewModel = new ViewModelProvider((ViewModelStoreOwner) context).get(PlaylistsVM.class);
viewModel.manage(PlaylistsVM.action.DELETE_PLAYLIST, playlist, null).observe((LifecycleOwner) context, apiResponse -> manageVIewPlaylists(PlaylistsVM.action.DELETE_PLAYLIST, apiResponse));
if (playlists.size() == 0 && textviewNoAction != null && textviewNoAction.getVisibility() == View.GONE) } else {
textviewNoAction.setVisibility(View.VISIBLE); new Thread(() -> {
SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new ManagePlaylistsDAO(context, db).removePlaylist(playlist.getUuid());
}).start();
}
if (playlists.size() == 0) {
allPlaylistRemoved.onAllPlaylistRemoved();
}
dialog.dismiss(); dialog.dismiss();
}) })
.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss()) .setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
@ -145,26 +175,116 @@ public class PlaylistAdapter extends BaseAdapter {
if (context instanceof AllPlaylistsActivity) { if (context instanceof AllPlaylistsActivity) {
((AllPlaylistsActivity) context).manageAlert(playlist); ((AllPlaylistsActivity) context).manageAlert(playlist);
} }
} else if (itemId == R.id.action_export) {
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
} else {
doExport(playlist);
}
} else {
doExport(playlist);
}
} }
return true; return true;
}); });
popup.show(); popup.show();
}); });
return convertView;
} }
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return playlists.size();
}
private void doExport(Playlist playlist) {
new Thread(() -> {
File file = null;
RetrofitPeertubeAPI retrofitPeertubeAPI = new RetrofitPeertubeAPI(context);
APIResponse apiResponse = retrofitPeertubeAPI.playlistAction(GET_LIST_VIDEOS, playlist.getId(), null, null, null);
if (apiResponse != null) {
List<VideoPlaylistData.VideoPlaylist> videos = apiResponse.getVideoPlaylist();
VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = new VideoPlaylistData.VideoPlaylistExport();
videoPlaylistExport.setPlaylist(playlist);
videoPlaylistExport.setUuid(playlist.getUuid());
videoPlaylistExport.setAcct(MainActivity.userMe.getAccount().getAcct());
videoPlaylistExport.setVideos(videos);
String data = PlaylistExportHelper.playlistToStringStorage(videoPlaylistExport);
File root = new File(Environment.getExternalStorageDirectory(), context.getString(R.string.app_name));
if (!root.exists()) {
//noinspection ResultOfMethodCallIgnored
root.mkdirs();
}
file = new File(root, "playlist_" + playlist.getUuid() + ".tubelab");
FileWriter writer;
try {
writer = new FileWriter(file);
writer.append(data);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> Toasty.error(context, context.getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
mainHandler.post(myRunnable);
return;
}
}
String urlAvatar = playlist.getThumbnailPath() != null ? Helper.getLiveInstance(context) + playlist.getThumbnailPath() : null;
FutureTarget<Bitmap> futureBitmapChannel = Glide.with(context.getApplicationContext())
.asBitmap()
.load(urlAvatar != null ? urlAvatar : R.drawable.missing_peertube).submit();
Bitmap icon = null;
try {
icon = futureBitmapChannel.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
if (file != null) {
Intent mailIntent = new Intent(Intent.ACTION_SEND);
mailIntent.setType("message/rfc822");
Uri contentUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileProvider", file);
mailIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.export_notification_subjet));
mailIntent.putExtra(Intent.EXTRA_TEXT, context.getString(R.string.export_notification_body));
mailIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
NotificationHelper.notify_user(context.getApplicationContext(),
playlist.getOwnerAccount(), mailIntent, icon,
context.getString(R.string.export_notification_title),
context.getString(R.string.export_notification_content));
}
}).start();
}
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) { public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) {
} }
private static class ViewHolder { public interface AllPlaylistRemoved {
LinearLayout playlist_container; void onAllPlaylistRemoved();
ImageView preview_playlist;
TextView preview_title, preview_visibility, preview_description;
ImageButton playlist_more;
} }
static class ViewHolder extends RecyclerView.ViewHolder {
DrawerPlaylistBinding binding;
ViewHolder(DrawerPlaylistBinding itemView) {
super(itemView.getRoot());
binding = itemView;
}
}
} }

View File

@ -54,7 +54,6 @@ public class DisplayAccountsFragment extends Fragment implements AccountsListAda
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction; private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad; private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private boolean swiped;
private RecyclerView lv_accounts; private RecyclerView lv_accounts;
private View rootView; private View rootView;
private RetrofitPeertubeAPI.DataType accountFetch; private RetrofitPeertubeAPI.DataType accountFetch;
@ -75,7 +74,6 @@ public class DisplayAccountsFragment extends Fragment implements AccountsListAda
max_id = null; max_id = null;
firstLoad = true; firstLoad = true;
flag_loading = true; flag_loading = true;
swiped = false;
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer); swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
@ -167,7 +165,6 @@ public class DisplayAccountsFragment extends Fragment implements AccountsListAda
if (apiResponse.getError() != null) { if (apiResponse.getError() != null) {
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
swiped = false;
flag_loading = false; flag_loading = false;
return; return;
} }
@ -180,22 +177,24 @@ public class DisplayAccountsFragment extends Fragment implements AccountsListAda
accounts.add(block.getBlockedAccount()); accounts.add(block.getBlockedAccount());
} }
} }
if (max_id == null) {
if (!swiped && firstLoad && (accounts == null || accounts.size() == 0)) max_id = "0";
}
if (firstLoad && (accounts == null || accounts.size() == 0))
textviewNoAction.setVisibility(View.VISIBLE); textviewNoAction.setVisibility(View.VISIBLE);
else else
textviewNoAction.setVisibility(View.GONE); textviewNoAction.setVisibility(View.GONE);
max_id = String.valueOf(Integer.parseInt(max_id) + 20);
max_id = apiResponse.getMax_id();
if (swiped) {
accountsListAdapter = new AccountsListAdapter(accountFetch, this.accounts);
lv_accounts.setAdapter(accountsListAdapter);
swiped = false;
}
if (accounts != null && accounts.size() > 0) { if (accounts != null && accounts.size() > 0) {
int previousPosition = this.accounts.size();
int currentPosition = this.accounts.size(); int currentPosition = this.accounts.size();
this.accounts.addAll(accounts); this.accounts.addAll(accounts);
accountsListAdapter.notifyItemRangeChanged(currentPosition, accounts.size()); if (previousPosition == 0) {
accountsListAdapter = new AccountsListAdapter(accountFetch, this.accounts);
accountsListAdapter.allAccountsRemoved = this;
lv_accounts.setAdapter(accountsListAdapter);
} else
accountsListAdapter.notifyItemRangeChanged(currentPosition, accounts.size());
} }
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
firstLoad = false; firstLoad = false;
@ -206,7 +205,6 @@ public class DisplayAccountsFragment extends Fragment implements AccountsListAda
accounts = new ArrayList<>(); accounts = new ArrayList<>();
firstLoad = true; firstLoad = true;
flag_loading = true; flag_loading = true;
swiped = true;
swipeRefreshLayout.setRefreshing(true); swipeRefreshLayout.setRefreshing(true);
AccountsVM viewModel = new ViewModelProvider(this).get(AccountsVM.class); AccountsVM viewModel = new ViewModelProvider(this).get(AccountsVM.class);
viewModel.getAccounts(RetrofitPeertubeAPI.DataType.MUTED, null).observe(DisplayAccountsFragment.this.requireActivity(), this::manageViewAccounts); viewModel.getAccounts(RetrofitPeertubeAPI.DataType.MUTED, null).observe(DisplayAccountsFragment.this.requireActivity(), this::manageViewAccounts);

View File

@ -14,8 +14,12 @@ package app.fedilab.fedilabtube.fragment;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -25,20 +29,21 @@ import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,44 +54,47 @@ import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.ChannelData; import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.client.entities.ChannelParams; import app.fedilab.fedilabtube.client.entities.ChannelParams;
import app.fedilab.fedilabtube.databinding.AddChannelBinding;
import app.fedilab.fedilabtube.databinding.FragmentRecyclerviewBinding;
import app.fedilab.fedilabtube.drawer.ChannelListAdapter; import app.fedilab.fedilabtube.drawer.ChannelListAdapter;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
import app.fedilab.fedilabtube.viewmodel.SearchVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
public class DisplayChannelsFragment extends Fragment implements ChannelListAdapter.AllChannelRemoved, ChannelListAdapter.EditAlertDialog { public class DisplayChannelsFragment extends Fragment implements ChannelListAdapter.AllChannelRemoved, ChannelListAdapter.EditAlertDialog {
private Context context; private Context context;
private static final int PICK_AVATAR = 467;
private ChannelListAdapter channelListAdapter; private ChannelListAdapter channelListAdapter;
private List<ChannelData.Channel> channels; private List<ChannelData.Channel> channels;
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private SwipeRefreshLayout swipeRefreshLayout;
private String name; private String name;
private boolean swiped;
private RecyclerView lv_channels;
private View rootView; private View rootView;
private FloatingActionButton action_button; private FloatingActionButton action_button;
private boolean myChannels; private FragmentRecyclerviewBinding binding;
private AddChannelBinding bindingDialog;
private Uri inputData;
private String search_peertube;
private String max_id;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_recyclerview, container, false);
binding = FragmentRecyclerviewBinding.inflate(LayoutInflater.from(context));
rootView = binding.getRoot();
context = getContext(); context = getContext();
Bundle bundle = this.getArguments(); Bundle bundle = this.getArguments();
channels = new ArrayList<>(); channels = new ArrayList<>();
myChannels = true; max_id = "0";
if (bundle != null) { if (bundle != null) {
name = bundle.getString("name", null); name = bundle.getString("name", null);
myChannels = bundle.getBoolean("myChannels", true); search_peertube = bundle.getString("search_peertube", null);
} }
swiped = false;
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
if (getActivity() != null) { if (getActivity() != null) {
action_button = getActivity().findViewById(R.id.action_button); action_button = getActivity().findViewById(R.id.action_button);
if (action_button != null) { if (action_button != null) {
@ -95,32 +103,54 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
} }
} }
lv_channels = rootView.findViewById(R.id.lv_elements); binding.lvElements.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
lv_channels.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL)); channelListAdapter = new ChannelListAdapter(this.channels);
mainLoader = rootView.findViewById(R.id.loader);
nextElementLoader = rootView.findViewById(R.id.loading_next);
textviewNoAction = rootView.findViewById(R.id.no_action);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
channelListAdapter = new ChannelListAdapter(this.channels, myChannels);
channelListAdapter.allChannelRemoved = this; channelListAdapter.allChannelRemoved = this;
channelListAdapter.editAlertDialog = this; channelListAdapter.editAlertDialog = this;
lv_channels.setAdapter(channelListAdapter); binding.lvElements.setAdapter(channelListAdapter);
final LinearLayoutManager mLayoutManager; final LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(context); mLayoutManager = new LinearLayoutManager(context);
lv_channels.setLayoutManager(mLayoutManager); binding.lvElements.setLayoutManager(mLayoutManager);
swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh); binding.swipeContainer.setOnRefreshListener(this::pullToRefresh);
ChannelsVM viewModel = new ViewModelProvider(this).get(ChannelsVM.class);
if (name != null) { loadChannels(max_id);
viewModel.get(RetrofitPeertubeAPI.DataType.CHANNELS_FOR_ACCOUNT, name).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
} else {
viewModel.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
}
return rootView; return rootView;
} }
private void loadChannels(String max_id) {
if (search_peertube == null) {
ChannelsVM viewModel = new ViewModelProvider(this).get(ChannelsVM.class);
if (name != null) {
viewModel.get(RetrofitPeertubeAPI.DataType.CHANNELS_FOR_ACCOUNT, name).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
} else {
viewModel.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
}
} else {
SearchVM viewModelSearch = new ViewModelProvider(this).get(SearchVM.class);
viewModelSearch.getChannels(max_id, search_peertube).observe(this.requireActivity(), this::manageViewChannels);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_AVATAR && resultCode == Activity.RESULT_OK) {
if (data == null || data.getData() == null) {
Toasty.error(context, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return;
}
inputData = data.getData();
Glide.with(context)
.load(inputData)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(bindingDialog.profilePicture);
}
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@ -155,103 +185,129 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
} }
public void scrollToTop() { public void scrollToTop() {
if (lv_channels != null) binding.lvElements.setAdapter(channelListAdapter);
lv_channels.setAdapter(channelListAdapter);
} }
private void manageViewChannels(APIResponse apiResponse) { private void manageViewChannels(APIResponse apiResponse) {
mainLoader.setVisibility(View.GONE); binding.loader.setVisibility(View.GONE);
nextElementLoader.setVisibility(View.GONE); binding.loadingNext.setVisibility(View.GONE);
if (apiResponse.getError() != null) { if (apiResponse.getError() != null) {
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
swiped = false;
return; return;
} }
List<ChannelData.Channel> channels = apiResponse.getChannels(); List<ChannelData.Channel> channels = apiResponse.getChannels();
if (!swiped && (channels == null || channels.size() == 0))
textviewNoAction.setVisibility(View.VISIBLE);
else
textviewNoAction.setVisibility(View.GONE);
if (swiped) { if ((channels == null || channels.size() == 0))
channelListAdapter = new ChannelListAdapter(this.channels, myChannels); binding.noAction.setVisibility(View.VISIBLE);
channelListAdapter.allChannelRemoved = DisplayChannelsFragment.this; else
channelListAdapter.editAlertDialog = DisplayChannelsFragment.this; binding.noAction.setVisibility(View.GONE);
lv_channels.setAdapter(channelListAdapter); max_id = String.valueOf(Integer.parseInt(max_id) + 20);
swiped = false;
}
if (channels != null && channels.size() > 0) { if (channels != null && channels.size() > 0) {
int currentPosition = this.channels.size(); int currentPosition = this.channels.size();
this.channels.addAll(channels); this.channels.addAll(channels);
channelListAdapter.notifyItemRangeChanged(currentPosition, channels.size()); if (currentPosition == 0) {
channelListAdapter = new ChannelListAdapter(this.channels);
channelListAdapter.allChannelRemoved = DisplayChannelsFragment.this;
channelListAdapter.editAlertDialog = DisplayChannelsFragment.this;
binding.lvElements.setAdapter(channelListAdapter);
} else {
channelListAdapter.notifyItemRangeChanged(currentPosition, channels.size());
}
} }
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
} }
public void pullToRefresh() { public void pullToRefresh() {
channels = new ArrayList<>(); channels = new ArrayList<>();
binding.swipeContainer.setRefreshing(true);
swiped = true; loadChannels("0");
swipeRefreshLayout.setRefreshing(true);
ChannelsVM viewModel = new ViewModelProvider(this).get(ChannelsVM.class);
if (name != null) {
viewModel.get(RetrofitPeertubeAPI.DataType.CHANNELS_FOR_ACCOUNT, name).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
} else {
viewModel.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
}
} }
@Override @Override
public void onAllChannelRemoved() { public void onAllChannelRemoved() {
textviewNoAction.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.VISIBLE);
} }
public void manageAlert(ChannelParams oldChannelValues) { public void manageAlert(ChannelParams oldChannelValues) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
LayoutInflater inflater1 = ((Activity) context).getLayoutInflater(); bindingDialog = AddChannelBinding.inflate(LayoutInflater.from(context), null, false);
View dialogView = inflater1.inflate(R.layout.add_channel, new LinearLayout(context), false); dialogBuilder.setView(bindingDialog.getRoot());
dialogBuilder.setView(dialogView);
EditText display_name = dialogView.findViewById(R.id.display_name);
EditText name = dialogView.findViewById(R.id.name);
EditText description = dialogView.findViewById(R.id.description);
if (oldChannelValues != null) { if (oldChannelValues != null) {
display_name.setText(oldChannelValues.getDisplayName()); bindingDialog.displayName.setText(oldChannelValues.getDisplayName());
name.setText(oldChannelValues.getName()); bindingDialog.name.setText(oldChannelValues.getName());
description.setText(oldChannelValues.getDescription()); bindingDialog.description.setText(oldChannelValues.getDescription());
name.setEnabled(false); bindingDialog.name.setEnabled(false);
} }
dialogBuilder.setPositiveButton(R.string.validate, null); dialogBuilder.setPositiveButton(R.string.validate, null);
dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alertDialog = dialogBuilder.create(); AlertDialog alertDialog = dialogBuilder.create();
int position;
if (oldChannelValues == null) {
position = -1;
} else {
position = 0;
for (ChannelData.Channel channel : channels) {
if (channel.getName().compareTo(oldChannelValues.getName()) == 0) {
break;
}
position++;
}
}
bindingDialog.selectFile.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
return;
}
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
String[] mimetypes = {"image/*"};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, PICK_AVATAR);
});
if (position >= 0) {
Helper.loadGiF(context, channels.get(position).getAvatar() != null ? channels.get(position).getAvatar().getPath() : null, bindingDialog.profilePicture);
} else {
Glide.with(context)
.load(R.drawable.missing_peertube)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(bindingDialog.profilePicture);
}
int finalPosition = position;
alertDialog.setOnShowListener(dialogInterface -> { alertDialog.setOnShowListener(dialogInterface -> {
Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(view -> { button.setOnClickListener(view -> {
if (display_name.getText() != null && display_name.getText().toString().trim().length() > 0 && name.getText() != null && name.getText().toString().trim().length() > 0) { if (bindingDialog.displayName.getText() != null && bindingDialog.displayName.getText().toString().trim().length() > 0 && bindingDialog.name.getText() != null && bindingDialog.name.getText().toString().trim().length() > 0) {
ChannelParams channelCreation = new ChannelParams(); ChannelParams channelCreation = new ChannelParams();
channelCreation.setDisplayName(display_name.getText().toString().trim()); channelCreation.setDisplayName(bindingDialog.displayName.getText().toString().trim());
channelCreation.setName(name.getText().toString().trim()); channelCreation.setName(bindingDialog.name.getText().toString().trim());
if (description.getText() != null && description.getText().toString().trim().length() > 0) { if (bindingDialog.description.getText() != null && bindingDialog.description.getText().toString().trim().length() > 0) {
channelCreation.setDescription(description.getText().toString().trim()); channelCreation.setDescription(bindingDialog.description.getText().toString().trim());
} }
new Thread(() -> { new Thread(() -> {
APIResponse apiResponse; APIResponse apiResponse;
if (oldChannelValues == null) { if (oldChannelValues == null) {
apiResponse = new RetrofitPeertubeAPI(context).createOrUpdateChannel(ChannelsVM.action.CREATE_CHANNEL, null, channelCreation); apiResponse = new RetrofitPeertubeAPI(context).createOrUpdateChannel(ChannelsVM.action.CREATE_CHANNEL, null, channelCreation, inputData);
} else { } else {
apiResponse = new RetrofitPeertubeAPI(context).createOrUpdateChannel(ChannelsVM.action.UPDATE_CHANNEL, channelCreation.getName() + "@" + Helper.getLiveInstance(context), channelCreation); apiResponse = new RetrofitPeertubeAPI(context).createOrUpdateChannel(ChannelsVM.action.UPDATE_CHANNEL, channelCreation.getName() + "@" + Helper.getLiveInstance(context), channelCreation, inputData);
} }
Handler mainHandler = new Handler(Looper.getMainLooper()); Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> { Runnable myRunnable = () -> {
if (getActivity() == null)
return;
if (oldChannelValues == null) { if (oldChannelValues == null) {
ChannelData.Channel channel = new ChannelData.Channel(); ChannelData.Channel channel = new ChannelData.Channel();
channel.setId(apiResponse.getActionReturn()); channel.setId(apiResponse.getActionReturn());
@ -261,16 +317,10 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
channels.add(0, channel); channels.add(0, channel);
channelListAdapter.notifyItemInserted(0); channelListAdapter.notifyItemInserted(0);
} else { } else {
int position = 0; channels.get(finalPosition).setName(channelCreation.getName());
for (ChannelData.Channel channel : channels) { channels.get(finalPosition).setDisplayName(channelCreation.getDisplayName());
if (channel.getName().compareTo(oldChannelValues.getName()) == 0) { channels.get(finalPosition).setDescription(channelCreation.getDescription());
channel.setDescription(channelCreation.getDescription()); channelListAdapter.notifyItemChanged(finalPosition);
channel.setDisplayName(channelCreation.getDisplayName());
break;
}
position++;
}
channelListAdapter.notifyItemChanged(position);
} }
if (action_button != null) { if (action_button != null) {
action_button.setEnabled(true); action_button.setEnabled(true);
@ -296,7 +346,7 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
//Hide keyboard //Hide keyboard
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
assert imm != null; assert imm != null;
imm.hideSoftInputFromWindow(display_name.getWindowToken(), 0); imm.hideSoftInputFromWindow(bindingDialog.displayName.getWindowToken(), 0);
}); });
if (alertDialog.getWindow() != null) if (alertDialog.getWindow() != null)
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

View File

@ -42,16 +42,28 @@ import app.fedilab.fedilabtube.viewmodel.NotificationsVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@SuppressWarnings({"unused", "RedundantSuppression"})
public class DisplayNotificationsFragment extends Fragment { public class DisplayNotificationsFragment extends Fragment {
//Peertube notification type //Peertube notification type
public static int NEW_VIDEO_FROM_SUBSCRIPTION = 1; public final static int NEW_VIDEO_FROM_SUBSCRIPTION = 1;
public static int UNBLACKLIST_ON_MY_VIDEO = 5; public final static int NEW_COMMENT_ON_MY_VIDEO = 2;
public static int BLACKLIST_ON_MY_VIDEO = 4; public final static int NEW_ABUSE_FOR_MODERATORS = 3;
public static int MY_VIDEO_PUBLISHED = 6; public final static int BLACKLIST_ON_MY_VIDEO = 4;
public static int MY_VIDEO_IMPORT_SUCCESS = 7; public final static int UNBLACKLIST_ON_MY_VIDEO = 5;
public static int MY_VIDEO_IMPORT_ERROR = 8; public final static int MY_VIDEO_PUBLISHED = 6;
public static int MY_VIDEO_REPPORT_SUCCESS = 15; public final static int MY_VIDEO_IMPORT_SUCCESS = 7;
public final static int MY_VIDEO_IMPORT_ERROR = 8;
public final static int NEW_USER_REGISTRATION = 9;
public final static int NEW_FOLLOW = 10;
public final static int COMMENT_MENTION = 11;
public final static int VIDEO_AUTO_BLACKLIST_FOR_MODERATORS = 12;
public final static int NEW_INSTANCE_FOLLOWER = 13;
public final static int AUTO_INSTANCE_FOLLOWING = 14;
public final static int MY_VIDEO_REPPORT_SUCCESS = 15;
public final static int ABUSE_NEW_MESSAGE = 16;
private boolean flag_loading; private boolean flag_loading;
private Context context; private Context context;
private PeertubeNotificationsListAdapter peertubeNotificationsListAdapter; private PeertubeNotificationsListAdapter peertubeNotificationsListAdapter;
@ -60,9 +72,9 @@ public class DisplayNotificationsFragment extends Fragment {
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction; private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad; private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private boolean swiped;
private RecyclerView lv_notifications; private RecyclerView lv_notifications;
private View rootView; private View rootView;
private NotificationsVM viewModel;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -74,10 +86,10 @@ public class DisplayNotificationsFragment extends Fragment {
max_id = "0"; max_id = "0";
firstLoad = true; firstLoad = true;
flag_loading = true; flag_loading = true;
swiped = false;
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer); swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
viewModel = new ViewModelProvider(this).get(NotificationsVM.class);
lv_notifications = rootView.findViewById(R.id.lv_elements); lv_notifications = rootView.findViewById(R.id.lv_elements);
lv_notifications.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL)); lv_notifications.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
@ -103,7 +115,6 @@ public class DisplayNotificationsFragment extends Fragment {
if (firstVisibleItem + visibleItemCount == totalItemCount) { if (firstVisibleItem + visibleItemCount == totalItemCount) {
if (!flag_loading) { if (!flag_loading) {
flag_loading = true; flag_loading = true;
NotificationsVM viewModel = new ViewModelProvider(DisplayNotificationsFragment.this).get(NotificationsVM.class);
viewModel.getNotifications(null, max_id).observe(DisplayNotificationsFragment.this.requireActivity(), apiResponse -> manageVIewNotifications(apiResponse)); viewModel.getNotifications(null, max_id).observe(DisplayNotificationsFragment.this.requireActivity(), apiResponse -> manageVIewNotifications(apiResponse));
nextElementLoader.setVisibility(View.VISIBLE); nextElementLoader.setVisibility(View.VISIBLE);
} }
@ -115,8 +126,7 @@ public class DisplayNotificationsFragment extends Fragment {
}); });
swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh); swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh);
NotificationsVM viewModel = new ViewModelProvider(this).get(NotificationsVM.class); viewModel.getNotifications(null, "0").observe(DisplayNotificationsFragment.this.requireActivity(), this::manageVIewNotifications);
viewModel.getNotifications(null, null).observe(DisplayNotificationsFragment.this.requireActivity(), this::manageVIewNotifications);
return rootView; return rootView;
} }
@ -126,9 +136,22 @@ public class DisplayNotificationsFragment extends Fragment {
rootView = null; rootView = null;
} }
@Override
public void onPause() {
super.onPause();
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setEnabled(false);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.clearAnimation();
}
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
swipeRefreshLayout.setEnabled(true);
if (getActivity() != null && getActivity() != null) { if (getActivity() != null && getActivity() != null) {
View action_button = getActivity().findViewById(R.id.action_button); View action_button = getActivity().findViewById(R.id.action_button);
if (action_button != null) { if (action_button != null) {
@ -160,15 +183,15 @@ public class DisplayNotificationsFragment extends Fragment {
public void pullToRefresh() { public void pullToRefresh() {
max_id = "0"; int size = notifications.size();
notifications.clear();
notifications = new ArrayList<>(); notifications = new ArrayList<>();
max_id = "0";
peertubeNotificationsListAdapter.notifyItemRangeRemoved(0, size);
firstLoad = true; firstLoad = true;
flag_loading = true; flag_loading = true;
swiped = true;
swipeRefreshLayout.setRefreshing(true); swipeRefreshLayout.setRefreshing(true);
NotificationsVM viewModel = new ViewModelProvider(this).get(NotificationsVM.class); viewModel.getNotifications(null, "0").observe(DisplayNotificationsFragment.this.requireActivity(), this::manageVIewNotifications);
viewModel.getNotifications(null, null).observe(DisplayNotificationsFragment.this.requireActivity(), this::manageVIewNotifications);
} }
private void manageVIewNotifications(APIResponse apiResponse) { private void manageVIewNotifications(APIResponse apiResponse) {
@ -178,28 +201,25 @@ public class DisplayNotificationsFragment extends Fragment {
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
flag_loading = false; flag_loading = false;
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
swiped = false;
return; return;
} }
int previousPosition = notifications.size(); int previousPosition = notifications.size();
max_id = String.valueOf(Integer.parseInt(max_id) + 20); max_id = String.valueOf(Integer.parseInt(max_id) + 20);
List<Notification> notifications = apiResponse.getPeertubeNotifications(); List<Notification> notifications = apiResponse.getPeertubeNotifications();
if (!swiped && firstLoad && (notifications == null || notifications.size() == 0)) if (firstLoad && (notifications == null || notifications.size() == 0))
textviewNoAction.setVisibility(View.VISIBLE); textviewNoAction.setVisibility(View.VISIBLE);
else else
textviewNoAction.setVisibility(View.GONE); textviewNoAction.setVisibility(View.GONE);
if (swiped) {
if (previousPosition > 0) {
this.notifications.subList(0, previousPosition).clear();
peertubeNotificationsListAdapter.notifyItemRangeRemoved(0, previousPosition);
}
swiped = false;
}
if (notifications != null && notifications.size() > 0) { if (notifications != null && notifications.size() > 0) {
this.notifications.addAll(notifications); this.notifications.addAll(notifications);
peertubeNotificationsListAdapter.notifyItemRangeInserted(previousPosition, notifications.size()); if (previousPosition == 0) {
peertubeNotificationsListAdapter = new PeertubeNotificationsListAdapter(this.notifications);
lv_notifications.setAdapter(peertubeNotificationsListAdapter);
} else
peertubeNotificationsListAdapter.notifyItemRangeInserted(previousPosition, notifications.size());
} else { } else {
if (firstLoad) if (firstLoad)
textviewNoAction.setVisibility(View.VISIBLE); textviewNoAction.setVisibility(View.VISIBLE);

View File

@ -39,6 +39,7 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
@ -64,8 +65,8 @@ import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; import app.fedilab.fedilabtube.viewmodel.PlaylistsVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.MY_CHANNELS; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.MY_CHANNELS;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
public class DisplayPlaylistsFragment extends Fragment { public class DisplayPlaylistsFragment extends Fragment {
@ -93,14 +94,14 @@ public class DisplayPlaylistsFragment extends Fragment {
playlists = new ArrayList<>(); playlists = new ArrayList<>();
ListView lv_playlist = rootView.findViewById(R.id.lv_playlist); RecyclerView lv_playlist = rootView.findViewById(R.id.lv_playlist);
textviewNoAction = rootView.findViewById(R.id.no_action); textviewNoAction = rootView.findViewById(R.id.no_action);
mainLoader = rootView.findViewById(R.id.loader); mainLoader = rootView.findViewById(R.id.loader);
RelativeLayout nextElementLoader = rootView.findViewById(R.id.loading_next_items); RelativeLayout nextElementLoader = rootView.findViewById(R.id.loading_next_items);
mainLoader.setVisibility(View.VISIBLE); mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE); nextElementLoader.setVisibility(View.GONE);
playlists = new ArrayList<>(); playlists = new ArrayList<>();
playlistAdapter = new PlaylistAdapter(context, playlists, textviewNoAction); playlistAdapter = new PlaylistAdapter(playlists, false);
lv_playlist.setAdapter(playlistAdapter); lv_playlist.setAdapter(playlistAdapter);
PlaylistsVM viewModel = new ViewModelProvider(this).get(PlaylistsVM.class); PlaylistsVM viewModel = new ViewModelProvider(this).get(PlaylistsVM.class);
viewModel.manage(PlaylistsVM.action.GET_PLAYLISTS, null, null).observe(DisplayPlaylistsFragment.this.requireActivity(), apiResponse -> manageVIewPlaylists(PlaylistsVM.action.GET_PLAYLISTS, apiResponse)); viewModel.manage(PlaylistsVM.action.GET_PLAYLISTS, null, null).observe(DisplayPlaylistsFragment.this.requireActivity(), apiResponse -> manageVIewPlaylists(PlaylistsVM.action.GET_PLAYLISTS, apiResponse));

View File

@ -22,17 +22,15 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -41,8 +39,10 @@ import java.util.List;
import app.fedilab.fedilabtube.BuildConfig; import app.fedilab.fedilabtube.BuildConfig;
import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.SepiaSearch; import app.fedilab.fedilabtube.client.entities.SepiaSearch;
import app.fedilab.fedilabtube.databinding.FragmentVideoBinding;
import app.fedilab.fedilabtube.drawer.AccountsHorizontalListAdapter; import app.fedilab.fedilabtube.drawer.AccountsHorizontalListAdapter;
import app.fedilab.fedilabtube.drawer.PeertubeAdapter; import app.fedilab.fedilabtube.drawer.PeertubeAdapter;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
@ -61,23 +61,24 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
private Context context; private Context context;
private PeertubeAdapter peertubeAdapater; private PeertubeAdapter peertubeAdapater;
private List<VideoData.Video> peertubes; private List<VideoData.Video> peertubes;
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad; private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout;
private SharedPreferences sharedpreferences; private SharedPreferences sharedpreferences;
private TextView textviewNoActionText;
private View rootView;
private RecyclerView lv_status;
private SepiaSearchVM viewModelSearch; private SepiaSearchVM viewModelSearch;
private SepiaSearch sepiaSearchVideo; private SepiaSearch sepiaSearchVideo;
private FragmentVideoBinding binding;
public DisplaySepiaSearchFragment() { public DisplaySepiaSearchFragment() {
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_video, container, false); binding = FragmentVideoBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
peertubes = new ArrayList<>(); peertubes = new ArrayList<>();
context = getContext(); context = getContext();
@ -85,40 +86,35 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
if (bundle != null) { if (bundle != null) {
sepiaSearchVideo = bundle.getParcelable("sepiaSearchVideo"); sepiaSearchVideo = bundle.getParcelable("sepiaSearchVideo");
} }
lv_status = rootView.findViewById(R.id.lv_status);
flag_loading = true; flag_loading = true;
firstLoad = true; firstLoad = true;
assert context != null; assert context != null;
sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
mainLoader = rootView.findViewById(R.id.loader);
nextElementLoader = rootView.findViewById(R.id.loading_next_status); binding.loader.setVisibility(View.VISIBLE);
textviewNoAction = rootView.findViewById(R.id.no_action); binding.loadingNextVideos.setVisibility(View.GONE);
textviewNoActionText = rootView.findViewById(R.id.no_action_text);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true); peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true);
lv_status.setAdapter(peertubeAdapater); binding.lvVideos.setAdapter(peertubeAdapater);
if (!Helper.isTablet(context)) { if (!Helper.isTablet(context)) {
mLayoutManager = new LinearLayoutManager(context); mLayoutManager = new LinearLayoutManager(context);
lv_status.setLayoutManager(mLayoutManager); binding.lvVideos.setLayoutManager(mLayoutManager);
} else { } else {
gLayoutManager = new GridLayoutManager(context, 2); gLayoutManager = new GridLayoutManager(context, 2);
int spanCount = (int) Helper.convertDpToPixel(2, context); int spanCount = (int) Helper.convertDpToPixel(2, context);
int spacing = (int) Helper.convertDpToPixel(5, context); int spacing = (int) Helper.convertDpToPixel(5, context);
lv_status.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, true)); binding.lvVideos.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, true));
lv_status.setLayoutManager(gLayoutManager); binding.lvVideos.setLayoutManager(gLayoutManager);
} }
viewModelSearch = new ViewModelProvider(DisplaySepiaSearchFragment.this).get(SepiaSearchVM.class); viewModelSearch = new ViewModelProvider(DisplaySepiaSearchFragment.this).get(SepiaSearchVM.class);
swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh); binding.swipeContainer.setOnRefreshListener(this::pullToRefresh);
lv_status.addOnScrollListener(new RecyclerView.OnScrollListener() { binding.lvVideos.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (mLayoutManager != null) { if (mLayoutManager != null) {
int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
@ -129,10 +125,10 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
if (!flag_loading) { if (!flag_loading) {
flag_loading = true; flag_loading = true;
loadTimeline(); loadTimeline();
nextElementLoader.setVisibility(View.VISIBLE); binding.loadingNextVideos.setVisibility(View.VISIBLE);
} }
} else { } else {
nextElementLoader.setVisibility(View.GONE); binding.loadingNextVideos.setVisibility(View.GONE);
} }
} }
} else if (gLayoutManager != null) { } else if (gLayoutManager != null) {
@ -144,27 +140,26 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
if (!flag_loading) { if (!flag_loading) {
flag_loading = true; flag_loading = true;
loadTimeline(); loadTimeline();
nextElementLoader.setVisibility(View.VISIBLE); binding.loadingNextVideos.setVisibility(View.VISIBLE);
} }
} else { } else {
nextElementLoader.setVisibility(View.GONE); binding.loadingNextVideos.setVisibility(View.GONE);
} }
} }
} }
} }
}); });
loadTimeline(); loadTimeline();
return rootView;
} }
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
if (swipeRefreshLayout != null) { if (binding.swipeContainer != null) {
swipeRefreshLayout.setEnabled(false); binding.swipeContainer.setEnabled(false);
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
swipeRefreshLayout.clearAnimation(); binding.swipeContainer.clearAnimation();
} }
if (getActivity() != null) { if (getActivity() != null) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
@ -201,12 +196,12 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
private void manageVIewVideos(VideoData videoData) { private void manageVIewVideos(VideoData videoData) {
//hide loaders //hide loaders
mainLoader.setVisibility(View.GONE); binding.loader.setVisibility(View.GONE);
nextElementLoader.setVisibility(View.GONE); binding.loadingNextVideos.setVisibility(View.GONE);
//handle other API error //handle other API error
if (videoData == null || videoData.data == null) { if (videoData == null || videoData.data == null) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show(); Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
flag_loading = false; flag_loading = false;
return; return;
} }
@ -227,16 +222,16 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
//If no item were inserted previously the adapter is created //If no item were inserted previously the adapter is created
if (previousPosition == 0) { if (previousPosition == 0) {
peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true); peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true);
lv_status.setAdapter(peertubeAdapater); binding.lvVideos.setAdapter(peertubeAdapater);
} else } else
peertubeAdapater.notifyItemRangeInserted(previousPosition, videoData.data.size()); peertubeAdapater.notifyItemRangeInserted(previousPosition, videoData.data.size());
//remove handlers //remove handlers
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
textviewNoAction.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE);
if (firstLoad && (videoData.data == null || videoData.data.size() == 0)) { if (firstLoad && (videoData.data == null || videoData.data.size() == 0)) {
textviewNoActionText.setText(R.string.no_video_to_display); binding.noActionText.setText(R.string.no_video_to_display);
textviewNoAction.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.VISIBLE);
} }
flag_loading = false; flag_loading = false;
firstLoad = false; firstLoad = false;
@ -244,20 +239,19 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
@Override @Override
public void onDestroyView() { public void onDestroyView() {
if (lv_status != null) { if (binding.lvVideos != null) {
try { try {
lv_status.setAdapter(null); binding.lvVideos.setAdapter(null);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
super.onDestroyView(); super.onDestroyView();
rootView = null;
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
swipeRefreshLayout.setEnabled(true); binding.swipeContainer.setEnabled(true);
} }
@ -279,7 +273,7 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
} }
@Override @Override
public void click(String forAccount) { public void click(ChannelData.Channel forChannel) {
pullToRefresh(); pullToRefresh();
} }

View File

@ -23,21 +23,16 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -51,10 +46,12 @@ import app.fedilab.fedilabtube.MainActivity;
import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.AccountData;
import app.fedilab.fedilabtube.client.data.ChannelData; import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.data.VideoPlaylistData; import app.fedilab.fedilabtube.client.data.VideoPlaylistData;
import app.fedilab.fedilabtube.client.entities.PlaylistExist; import app.fedilab.fedilabtube.client.entities.PlaylistExist;
import app.fedilab.fedilabtube.databinding.FragmentVideoBinding;
import app.fedilab.fedilabtube.drawer.AccountsHorizontalListAdapter; import app.fedilab.fedilabtube.drawer.AccountsHorizontalListAdapter;
import app.fedilab.fedilabtube.drawer.PeertubeAdapter; import app.fedilab.fedilabtube.drawer.PeertubeAdapter;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
@ -65,6 +62,8 @@ import app.fedilab.fedilabtube.viewmodel.SearchVM;
import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.viewmodel.TimelineVM.TimelineType.VIDEOS_IN_LOCAL_PLAYLIST;
public class DisplayVideosFragment extends Fragment implements AccountsHorizontalListAdapter.EventListener, PeertubeAdapter.RelationShipListener, PeertubeAdapter.PlaylistListener { public class DisplayVideosFragment extends Fragment implements AccountsHorizontalListAdapter.EventListener, PeertubeAdapter.RelationShipListener, PeertubeAdapter.PlaylistListener {
@ -79,26 +78,23 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
private List<VideoData.Video> peertubes; private List<VideoData.Video> peertubes;
private List<ChannelData.Channel> channels; private List<ChannelData.Channel> channels;
private TimelineVM.TimelineType type; private TimelineVM.TimelineType type;
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad; private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout;
private SharedPreferences sharedpreferences;
private String search_peertube; private String search_peertube;
private TextView textviewNoActionText;
private View rootView;
private RecyclerView lv_status;
private boolean check_ScrollingUp; private boolean check_ScrollingUp;
private String forAccount; private ChannelData.Channel forChannel;
private ConstraintLayout top_account_container;
private TimelineVM viewModelFeeds; private TimelineVM viewModelFeeds;
private SearchVM viewModelSearch; private SearchVM viewModelSearch;
private AccountsVM viewModelAccounts; private AccountsVM viewModelAccounts;
private String channelId; private ChannelData.Channel channel;
private AccountData.Account account;
private Map<String, Boolean> relationship; private Map<String, Boolean> relationship;
private Map<String, List<PlaylistExist>> playlists; private Map<String, List<PlaylistExist>> playlists;
private String playlistId; private String playlistId;
private String remoteInstance; private String remoteInstance;
private boolean sepiaSearch; private boolean sepiaSearch;
private String startDate, endDate;
private FragmentVideoBinding binding;
private String channelId;
public DisplayVideosFragment() { public DisplayVideosFragment() {
} }
@ -106,69 +102,72 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_video, container, false); binding = FragmentVideoBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
peertubes = new ArrayList<>(); peertubes = new ArrayList<>();
channels = new ArrayList<>(); channels = new ArrayList<>();
context = getContext(); context = getContext();
startDate = null;
endDate = null;
Bundle bundle = this.getArguments(); Bundle bundle = this.getArguments();
if (bundle != null) { if (bundle != null) {
search_peertube = bundle.getString("search_peertube", null); search_peertube = bundle.getString("search_peertube", null);
channelId = bundle.getString("channelId", null); channel = bundle.getParcelable("channel");
account = bundle.getParcelable("account");
remoteInstance = bundle.getString("peertube_instance", null); remoteInstance = bundle.getString("peertube_instance", null);
sepiaSearch = bundle.getBoolean("sepia_search", false); sepiaSearch = bundle.getBoolean("sepia_search", false);
type = (TimelineVM.TimelineType) bundle.get(Helper.TIMELINE_TYPE); type = (TimelineVM.TimelineType) bundle.get(Helper.TIMELINE_TYPE);
playlistId = bundle.getString("playlistId", null); playlistId = bundle.getString("playlistId", null);
startDate = bundle.getString("startDate", null);
endDate = bundle.getString("endDate", null);
}
if (channel != null) {
channelId = channel.getAcct();
} else if (account != null) {
channelId = account.getAcct();
} }
max_id = "0"; max_id = "0";
forAccount = type == TimelineVM.TimelineType.ACCOUNT_VIDEOS ? channelId : null; //forChannel = type == TimelineVM.TimelineType.ACCOUNT_VIDEOS ? channelId : null;
lv_status = rootView.findViewById(R.id.lv_status);
RecyclerView lv_accounts = rootView.findViewById(R.id.lv_accounts);
Button display_all = rootView.findViewById(R.id.display_all);
top_account_container = rootView.findViewById(R.id.top_account_container);
max_id_accounts = null; max_id_accounts = null;
flag_loading = true; flag_loading = true;
firstLoad = true; firstLoad = true;
check_ScrollingUp = false; check_ScrollingUp = false;
assert context != null; binding.loader.setVisibility(View.VISIBLE);
sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); binding.loadingNextVideos.setVisibility(View.GONE);
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
mainLoader = rootView.findViewById(R.id.loader);
nextElementLoader = rootView.findViewById(R.id.loading_next_status);
textviewNoAction = rootView.findViewById(R.id.no_action);
textviewNoActionText = rootView.findViewById(R.id.no_action_text);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch); peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch);
peertubeAdapater.playlistListener = this; peertubeAdapater.playlistListener = this;
peertubeAdapater.relationShipListener = this; peertubeAdapater.relationShipListener = this;
lv_status.setAdapter(peertubeAdapater); binding.lvVideos.setAdapter(peertubeAdapater);
accountsHorizontalListAdapter = new AccountsHorizontalListAdapter(this.channels, this); accountsHorizontalListAdapter = new AccountsHorizontalListAdapter(this.channels, this);
LinearLayoutManager layoutManager LinearLayoutManager layoutManager
= new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false); = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
lv_accounts.setLayoutManager(layoutManager); binding.lvAccounts.setLayoutManager(layoutManager);
lv_accounts.setAdapter(accountsHorizontalListAdapter); binding.lvAccounts.setAdapter(accountsHorizontalListAdapter);
if (!Helper.isTablet(context)) { if (!Helper.isTablet(context)) {
mLayoutManager = new LinearLayoutManager(context); mLayoutManager = new LinearLayoutManager(context);
lv_status.setLayoutManager(mLayoutManager); binding.lvVideos.setLayoutManager(mLayoutManager);
} else { } else {
gLayoutManager = new GridLayoutManager(context, 2); gLayoutManager = new GridLayoutManager(context, 2);
int spanCount = (int) Helper.convertDpToPixel(2, context); int spanCount = (int) Helper.convertDpToPixel(2, context);
int spacing = (int) Helper.convertDpToPixel(5, context); int spacing = (int) Helper.convertDpToPixel(5, context);
lv_status.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, true)); binding.lvVideos.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, true));
lv_status.setLayoutManager(gLayoutManager); binding.lvVideos.setLayoutManager(gLayoutManager);
} }
viewModelAccounts = new ViewModelProvider(DisplayVideosFragment.this).get(AccountsVM.class); viewModelAccounts = new ViewModelProvider(DisplayVideosFragment.this).get(AccountsVM.class);
viewModelFeeds = new ViewModelProvider(DisplayVideosFragment.this).get(TimelineVM.class); viewModelFeeds = new ViewModelProvider(DisplayVideosFragment.this).get(TimelineVM.class);
viewModelSearch = new ViewModelProvider(DisplayVideosFragment.this).get(SearchVM.class); viewModelSearch = new ViewModelProvider(DisplayVideosFragment.this).get(SearchVM.class);
swipeRefreshLayout.setOnRefreshListener(() -> pullToRefresh(true)); binding.swipeContainer.setOnRefreshListener(() -> pullToRefresh(true));
lv_accounts.addOnScrollListener(new RecyclerView.OnScrollListener() { binding.lvAccounts.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
if (dy > 0) { if (dy > 0) {
@ -182,77 +181,84 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
}); });
lv_status.addOnScrollListener(new RecyclerView.OnScrollListener() { if (type != VIDEOS_IN_LOCAL_PLAYLIST) {
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { binding.lvVideos.addOnScrollListener(new RecyclerView.OnScrollListener() {
if (type == TimelineVM.TimelineType.SUBSCRIBTIONS) { public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) { if (type == TimelineVM.TimelineType.SUBSCRIBTIONS) {
if (check_ScrollingUp) { if (dy > 0) {
top_account_container.setVisibility(View.GONE); if (check_ScrollingUp) {
final Handler handler = new Handler(); binding.topAccountContainer.setVisibility(View.GONE);
handler.postDelayed(() -> check_ScrollingUp = false, 300); final Handler handler = new Handler();
handler.postDelayed(() -> check_ScrollingUp = false, 300);
}
} else {
if (!check_ScrollingUp) {
binding.topAccountContainer.setVisibility(View.VISIBLE);
final Handler handler = new Handler();
handler.postDelayed(() -> check_ScrollingUp = true, 300);
}
} }
} else { }
if (!check_ScrollingUp) { if (mLayoutManager != null) {
top_account_container.setVisibility(View.VISIBLE); int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
final Handler handler = new Handler(); if (dy > 0) {
handler.postDelayed(() -> check_ScrollingUp = true, 300); int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
if (!flag_loading) {
flag_loading = true;
loadTimeline(max_id);
binding.loadingNextVideos.setVisibility(View.VISIBLE);
}
} else {
binding.loadingNextVideos.setVisibility(View.GONE);
}
}
} else if (gLayoutManager != null) {
int firstVisibleItem = gLayoutManager.findFirstVisibleItemPosition();
if (dy > 0) {
int visibleItemCount = gLayoutManager.getChildCount();
int totalItemCount = gLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
if (!flag_loading) {
flag_loading = true;
loadTimeline(max_id);
binding.loadingNextVideos.setVisibility(View.VISIBLE);
}
} else {
binding.loadingNextVideos.setVisibility(View.GONE);
}
} }
} }
} }
if (mLayoutManager != null) { });
int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); }
if (dy > 0) {
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
if (!flag_loading) {
flag_loading = true;
loadTimeline(max_id);
nextElementLoader.setVisibility(View.VISIBLE);
}
} else {
nextElementLoader.setVisibility(View.GONE);
}
}
} else if (gLayoutManager != null) {
int firstVisibleItem = gLayoutManager.findFirstVisibleItemPosition();
if (dy > 0) {
int visibleItemCount = gLayoutManager.getChildCount();
int totalItemCount = gLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
if (!flag_loading) {
flag_loading = true;
loadTimeline(max_id);
nextElementLoader.setVisibility(View.VISIBLE);
}
} else {
nextElementLoader.setVisibility(View.GONE);
}
}
}
}
});
if (type == TimelineVM.TimelineType.SUBSCRIBTIONS) { if (type == TimelineVM.TimelineType.SUBSCRIBTIONS) {
AccountsVM viewModel = new ViewModelProvider(this).get(AccountsVM.class); AccountsVM viewModel = new ViewModelProvider(this).get(AccountsVM.class);
viewModel.getAccounts(RetrofitPeertubeAPI.DataType.SUBSCRIBER, max_id).observe(DisplayVideosFragment.this.requireActivity(), this::manageViewAccounts); viewModel.getAccounts(RetrofitPeertubeAPI.DataType.SUBSCRIBER, max_id).observe(DisplayVideosFragment.this.requireActivity(), this::manageViewAccounts);
} }
loadTimeline(max_id); loadTimeline(max_id);
display_all.setOnClickListener(v -> { binding.displayAll.setOnClickListener(v -> {
forAccount = null; forChannel = null;
pullToRefresh(false); pullToRefresh(false);
}); });
return rootView; }
@Override
public void onResume() {
super.onResume();
binding.swipeContainer.setEnabled(true);
} }
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
if (swipeRefreshLayout != null) { if (binding.swipeContainer != null) {
swipeRefreshLayout.setEnabled(false); binding.swipeContainer.setEnabled(false);
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
swipeRefreshLayout.clearAnimation(); binding.swipeContainer.clearAnimation();
} }
if (getActivity() != null) { if (getActivity() != null) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
@ -289,8 +295,8 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
private void manageViewAccounts(APIResponse apiResponse) { private void manageViewAccounts(APIResponse apiResponse) {
if (apiResponse != null && apiResponse.getChannels() != null && apiResponse.getChannels().size() > 0) { if (apiResponse != null && apiResponse.getChannels() != null && apiResponse.getChannels().size() > 0) {
if (top_account_container.getVisibility() == View.GONE) { if (binding.topAccountContainer.getVisibility() == View.GONE) {
top_account_container.setVisibility(View.VISIBLE); binding.topAccountContainer.setVisibility(View.VISIBLE);
} }
int previousPosition = channels.size(); int previousPosition = channels.size();
channels.addAll(apiResponse.getChannels()); channels.addAll(apiResponse.getChannels());
@ -298,6 +304,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
if (max_id_accounts == null) { if (max_id_accounts == null) {
max_id_accounts = "0"; max_id_accounts = "0";
} }
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
//max_id_accounts needs to work like an offset //max_id_accounts needs to work like an offset
int tootPerPage = sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE); int tootPerPage = sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE);
max_id_accounts = String.valueOf(Integer.parseInt(max_id_accounts) + tootPerPage); max_id_accounts = String.valueOf(Integer.parseInt(max_id_accounts) + tootPerPage);
@ -307,8 +314,8 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
private void manageVIewVideos(APIResponse apiResponse) { private void manageVIewVideos(APIResponse apiResponse) {
//hide loaders //hide loaders
mainLoader.setVisibility(View.GONE); binding.loader.setVisibility(View.GONE);
nextElementLoader.setVisibility(View.GONE); binding.loadingNextVideos.setVisibility(View.GONE);
//handle other API error //handle other API error
if (this.peertubes == null || apiResponse == null || (apiResponse.getError() != null)) { if (this.peertubes == null || apiResponse == null || (apiResponse.getError() != null)) {
if (apiResponse == null) if (apiResponse == null)
@ -316,7 +323,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
else { else {
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
} }
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
flag_loading = false; flag_loading = false;
return; return;
} }
@ -324,6 +331,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
if (max_id == null) if (max_id == null)
max_id = "0"; max_id = "0";
//max_id needs to work like an offset //max_id needs to work like an offset
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int videoPerPage = sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE); int videoPerPage = sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE);
max_id = String.valueOf(Integer.parseInt(max_id) + videoPerPage); max_id = String.valueOf(Integer.parseInt(max_id) + videoPerPage);
if (apiResponse.getPeertubes() == null && apiResponse.getVideoPlaylist() == null) { if (apiResponse.getPeertubes() == null && apiResponse.getVideoPlaylist() == null) {
@ -351,15 +359,15 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch); peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch);
peertubeAdapater.playlistListener = DisplayVideosFragment.this; peertubeAdapater.playlistListener = DisplayVideosFragment.this;
peertubeAdapater.relationShipListener = DisplayVideosFragment.this; peertubeAdapater.relationShipListener = DisplayVideosFragment.this;
lv_status.setAdapter(peertubeAdapater); binding.lvVideos.setAdapter(peertubeAdapater);
} else } else
peertubeAdapater.notifyItemRangeInserted(previousPosition, apiResponse.getPeertubes().size()); peertubeAdapater.notifyItemRangeInserted(previousPosition, apiResponse.getPeertubes().size());
//remove handlers //remove handlers
swipeRefreshLayout.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
textviewNoAction.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE);
if (firstLoad && (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().size() == 0)) { if (firstLoad && (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().size() == 0)) {
textviewNoActionText.setText(R.string.no_video_to_display); binding.noActionText.setText(R.string.no_video_to_display);
textviewNoAction.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.VISIBLE);
} }
flag_loading = false; flag_loading = false;
firstLoad = false; firstLoad = false;
@ -424,20 +432,13 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
@Override @Override
public void onDestroyView() { public void onDestroyView() {
if (lv_status != null) { if (binding.lvVideos != null) {
try { try {
lv_status.setAdapter(null); binding.lvVideos.setAdapter(null);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
super.onDestroyView(); super.onDestroyView();
rootView = null;
}
@Override
public void onResume() {
super.onResume();
swipeRefreshLayout.setEnabled(true);
} }
@ -452,28 +453,18 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
public void pullToRefresh(boolean reload) { public void pullToRefresh(boolean reload) {
if (type == TimelineVM.TimelineType.SUBSCRIBTIONS && reload) { if (type == TimelineVM.TimelineType.SUBSCRIBTIONS && reload) {
Fragment fragment = ((AppCompatActivity) context).getSupportFragmentManager().findFragmentByTag("2"); DisplayVideosFragment subscriptionFragment = ((MainActivity) context).getSubscriptionFragment();
if (fragment != null) { if (subscriptionFragment != null) {
if (context instanceof MainActivity) { FragmentTransaction ft = ((MainActivity) context).getSupportFragmentManager().beginTransaction();
FragmentManager fm = ((MainActivity) context).getSupportFragmentManager(); ft.detach(subscriptionFragment).attach(subscriptionFragment).commit();
fm.beginTransaction().remove(fragment).commit();
DisplayVideosFragment subscriptionFragment = new DisplayVideosFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.SUBSCRIBTIONS);
subscriptionFragment.setArguments(bundle);
((MainActivity) context).setActive(subscriptionFragment);
((MainActivity) context).setSubscriptionFragment(subscriptionFragment);
fm.beginTransaction().add(R.id.nav_host_fragment, subscriptionFragment, "2").commit();
}
} }
} else { } else {
int size = peertubes.size(); int size = peertubes.size();
peertubes.clear(); peertubes.clear();
peertubes = new ArrayList<>(); peertubes = new ArrayList<>();
max_id = "0"; max_id = "0";
peertubeAdapater.notifyItemRangeRemoved(0, size); peertubeAdapater.notifyItemRangeRemoved(0, size);
if (forAccount == null) { if (forChannel == null) {
for (ChannelData.Channel channel : channels) { for (ChannelData.Channel channel : channels) {
channel.setSelected(false); channel.setSelected(false);
} }
@ -485,8 +476,8 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
} }
@Override @Override
public void click(String forAccount) { public void click(ChannelData.Channel forChannel) {
this.forAccount = forAccount; this.forChannel = forChannel;
pullToRefresh(false); pullToRefresh(false);
} }
@ -501,8 +492,12 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
viewModelFeeds.getVideosInChannel(sepiaSearch ? remoteInstance : null, channelId, max_id).observe(this.requireActivity(), this::manageVIewVideos); viewModelFeeds.getVideosInChannel(sepiaSearch ? remoteInstance : null, channelId, max_id).observe(this.requireActivity(), this::manageVIewVideos);
} else if (type == TimelineVM.TimelineType.VIDEOS_IN_PLAYLIST) { } else if (type == TimelineVM.TimelineType.VIDEOS_IN_PLAYLIST) {
viewModelFeeds.loadVideosInPlaylist(playlistId, max_id).observe(this.requireActivity(), this::manageVIewVideos); viewModelFeeds.loadVideosInPlaylist(playlistId, max_id).observe(this.requireActivity(), this::manageVIewVideos);
} else if (type == VIDEOS_IN_LOCAL_PLAYLIST) {
viewModelFeeds.loadVideosInLocalPlaylist(playlistId).observe(this.requireActivity(), this::manageVIewVideos);
} else if (type == TimelineVM.TimelineType.HISTORY) {
viewModelFeeds.getVideoHistory(max_id, startDate, endDate).observe(this.requireActivity(), this::manageVIewVideos);
} else { } else {
viewModelFeeds.getVideos(type, max_id, forAccount).observe(this.requireActivity(), this::manageVIewVideos); viewModelFeeds.getVideos(type, max_id, forChannel, account).observe(this.requireActivity(), this::manageVIewVideos);
} }
} else { } else {
viewModelSearch.getVideos(max_id, search_peertube).observe(this.requireActivity(), this::manageVIewVideos); viewModelSearch.getVideos(max_id, search_peertube).observe(this.requireActivity(), this::manageVIewVideos);

View File

@ -1,17 +1,30 @@
package app.fedilab.fedilabtube.fragment; package app.fedilab.fedilabtube.fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.MultiSelectListPreference; import androidx.preference.MultiSelectListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SeekBarPreference; import androidx.preference.SeekBarPreference;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
@ -20,12 +33,16 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import app.fedilab.fedilabtube.MainActivity;
import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.UserSettings;
import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.helper.ThemeHelper; import app.fedilab.fedilabtube.helper.ThemeHelper;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation; import static app.fedilab.fedilabtube.MainActivity.userMe;
/* Copyright 2020 Thomas Schneider /* Copyright 2020 Thomas Schneider
* *
@ -81,11 +98,14 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL); editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
break; break;
case "1": case "1":
editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_STREAMING); editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_MAGNET);
break; break;
case "2": case "2":
editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_WEBVIEW); editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_WEBVIEW);
break; break;
case "3":
editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_TORRENT);
break;
} }
} }
@ -109,6 +129,26 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
ThemeHelper.switchTo(choice); ThemeHelper.switchTo(choice);
} }
} }
if (key.compareTo(getString(R.string.set_video_sensitive_choice)) == 0) {
ListPreference set_video_sensitive_choice = findPreference(getString(R.string.set_video_sensitive_choice));
if (set_video_sensitive_choice != null) {
editor.putString(getString(R.string.set_video_sensitive_choice), set_video_sensitive_choice.getValue());
editor.apply();
if (Helper.isLoggedIn(getActivity())) {
new Thread(() -> {
UserSettings userSettings = new UserSettings();
userSettings.setNsfwPolicy(set_video_sensitive_choice.getValue());
try {
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(getActivity());
api.updateUser(userSettings);
userMe.setNsfwPolicy(set_video_sensitive_choice.getValue());
} catch (Exception | Error e) {
e.printStackTrace();
}
}).start();
}
}
}
if (key.compareTo(getString(R.string.set_video_quality_choice)) == 0) { if (key.compareTo(getString(R.string.set_video_quality_choice)) == 0) {
ListPreference set_video_quality_choice = findPreference(getString(R.string.set_video_quality_choice)); ListPreference set_video_quality_choice = findPreference(getString(R.string.set_video_quality_choice));
if (set_video_quality_choice != null) { if (set_video_quality_choice != null) {
@ -141,16 +181,70 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
SwitchPreference set_autoplay_choice = findPreference(getString(R.string.set_autoplay_choice)); SwitchPreference set_autoplay_choice = findPreference(getString(R.string.set_autoplay_choice));
assert set_autoplay_choice != null; assert set_autoplay_choice != null;
editor.putBoolean(getString(R.string.set_autoplay_choice), set_autoplay_choice.isChecked()); editor.putBoolean(getString(R.string.set_autoplay_choice), set_autoplay_choice.isChecked());
if (Helper.isLoggedIn(getActivity())) {
new Thread(() -> {
UserSettings userSettings = new UserSettings();
userSettings.setAutoPlayVideo(set_autoplay_choice.isChecked());
try {
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(getActivity());
api.updateUser(userSettings);
} catch (Exception | Error e) {
e.printStackTrace();
}
}).start();
}
} }
if (key.compareTo(getString(R.string.set_fullscreen_choice)) == 0) { if (key.compareTo(getString(R.string.set_fullscreen_choice)) == 0) {
SwitchPreference set_fullscreen_choice = findPreference(getString(R.string.set_fullscreen_choice)); SwitchPreference set_fullscreen_choice = findPreference(getString(R.string.set_fullscreen_choice));
assert set_fullscreen_choice != null; assert set_fullscreen_choice != null;
editor.putBoolean(getString(R.string.set_fullscreen_choice), set_fullscreen_choice.isChecked()); editor.putBoolean(getString(R.string.set_fullscreen_choice), set_fullscreen_choice.isChecked());
} }
if (key.compareTo(getString(R.string.set_autoplay_next_video_choice)) == 0) {
SwitchPreference set_autoplay_next_video_choice = findPreference(getString(R.string.set_autoplay_next_video_choice));
assert set_autoplay_next_video_choice != null;
editor.putBoolean(getString(R.string.set_autoplay_next_video_choice), set_autoplay_next_video_choice.isChecked());
if (Helper.isLoggedIn(getActivity())) {
new Thread(() -> {
UserSettings userSettings = new UserSettings();
userSettings.setAutoPlayNextVideo(set_autoplay_next_video_choice.isChecked());
try {
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(getActivity());
api.updateUser(userSettings);
} catch (Exception | Error e) {
e.printStackTrace();
}
}).start();
}
}
if (key.compareTo(getString(R.string.set_play_screen_lock_choice)) == 0) {
SwitchPreference set_play_screen_lock_choice = findPreference(getString(R.string.set_play_screen_lock_choice));
assert set_play_screen_lock_choice != null;
editor.putBoolean(getString(R.string.set_play_screen_lock_choice), set_play_screen_lock_choice.isChecked());
}
if (key.compareTo(getString(R.string.set_video_in_list_choice)) == 0) {
SwitchPreference set_video_in_list_choice = findPreference(getString(R.string.set_video_in_list_choice));
assert set_video_in_list_choice != null;
editor.putBoolean(getString(R.string.set_video_in_list_choice), set_video_in_list_choice.isChecked());
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
}
if (key.compareTo(getString(R.string.set_video_language_choice)) == 0) { if (key.compareTo(getString(R.string.set_video_language_choice)) == 0) {
MultiSelectListPreference set_video_language_choice = findPreference(getString(R.string.set_video_language_choice)); MultiSelectListPreference set_video_language_choice = findPreference(getString(R.string.set_video_language_choice));
assert set_video_language_choice != null; assert set_video_language_choice != null;
editor.putStringSet(getString(R.string.set_video_language_choice), set_video_language_choice.getValues()); editor.putStringSet(getString(R.string.set_video_language_choice), set_video_language_choice.getValues());
if (Helper.isLoggedIn(getActivity())) {
new Thread(() -> {
UserSettings userSettings = new UserSettings();
Set<String> language_choiceValues = set_video_language_choice.getValues();
userSettings.setVideoLanguages(new ArrayList<>(language_choiceValues));
try {
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(getActivity());
api.updateUser(userSettings);
} catch (Exception | Error e) {
e.printStackTrace();
}
}).start();
}
} }
editor.apply(); editor.apply();
} }
@ -167,6 +261,39 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
return; return;
} }
//****** My Account ******
Preference my_account = findPreference("my_account");
assert my_account != null;
if (!Helper.isLoggedIn(getActivity()) || userMe == null) {
my_account.setVisible(false);
} else {
my_account.setTitle(userMe.getUsername());
my_account.setSummary(userMe.getEmail());
Resources resources = getResources();
Drawable defaultAvatar = ResourcesCompat.getDrawable(resources, R.drawable.missing_peertube, null);
my_account.setIcon(defaultAvatar);
String avatarUrl = null;
if (userMe.getAccount().getAvatar() != null) {
avatarUrl = "https://" + Helper.getLiveInstance(context) + userMe.getAccount().getAvatar().getPath();
}
Glide.with(getActivity())
.asDrawable()
.load(avatarUrl != null ? avatarUrl : R.drawable.missing_peertube)
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
my_account.setIcon(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
//****** App theme ******* //****** App theme *******
ListPreference set_theme_choice = findPreference(getString(R.string.set_theme_choice)); ListPreference set_theme_choice = findPreference(getString(R.string.set_theme_choice));
List<String> arrayTheme = Arrays.asList(getResources().getStringArray(R.array.settings_theme)); List<String> arrayTheme = Arrays.asList(getResources().getStringArray(R.array.settings_theme));
@ -183,15 +310,17 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
set_theme_choice.setValueIndex(currentTheme); set_theme_choice.setValueIndex(currentTheme);
} }
//****** Video mode ******* //****** Video mode *******
ListPreference set_video_mode_choice = findPreference(getString(R.string.set_video_mode_choice)); ListPreference set_video_mode_choice = findPreference(getString(R.string.set_video_mode_choice));
List<String> array = Arrays.asList(getResources().getStringArray(R.array.settings_video_mode)); List<String> array = Arrays.asList(getResources().getStringArray(R.array.settings_video_mode));
CharSequence[] entries = array.toArray(new CharSequence[0]); CharSequence[] entries = array.toArray(new CharSequence[0]);
CharSequence[] entryValues = new CharSequence[3]; CharSequence[] entryValues = new CharSequence[4];
int video_mode = sharedpref.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL); int video_mode = sharedpref.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
entryValues[0] = String.valueOf(Helper.VIDEO_MODE_NORMAL); entryValues[0] = String.valueOf(Helper.VIDEO_MODE_NORMAL);
entryValues[1] = String.valueOf(Helper.VIDEO_MODE_STREAMING); entryValues[1] = String.valueOf(Helper.VIDEO_MODE_MAGNET);
entryValues[2] = String.valueOf(Helper.VIDEO_MODE_WEBVIEW); entryValues[2] = String.valueOf(Helper.VIDEO_MODE_WEBVIEW);
entryValues[3] = String.valueOf(Helper.VIDEO_MODE_TORRENT);
if (set_video_mode_choice != null) { if (set_video_mode_choice != null) {
set_video_mode_choice.setEntries(entries); set_video_mode_choice.setEntries(entries);
set_video_mode_choice.setEntryValues(entryValues); set_video_mode_choice.setEntryValues(entryValues);
@ -223,6 +352,10 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
SwitchPreference set_video_minimize_choice = findPreference(getString(R.string.set_video_minimize_choice)); SwitchPreference set_video_minimize_choice = findPreference(getString(R.string.set_video_minimize_choice));
assert set_video_minimize_choice != null; assert set_video_minimize_choice != null;
set_video_minimize_choice.setChecked(minimized); set_video_minimize_choice.setChecked(minimized);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|| !getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
set_video_minimize_choice.setVisible(false);
}
//****** Autoplay videos ******* //****** Autoplay videos *******
@ -238,8 +371,28 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
assert set_fullscreen_choice != null; assert set_fullscreen_choice != null;
set_fullscreen_choice.setChecked(fullscreen); set_fullscreen_choice.setChecked(fullscreen);
//****** Autoplay next videos *******
boolean autoplayNextVideo = sharedpref.getBoolean(getString(R.string.set_autoplay_next_video_choice), false);
SwitchPreference set_autoplay_next_video_choice = findPreference(getString(R.string.set_autoplay_next_video_choice));
assert set_autoplay_next_video_choice != null;
set_autoplay_next_video_choice.setChecked(autoplayNextVideo);
//****** Screen lock *******
boolean playScreenLock = sharedpref.getBoolean(getString(R.string.set_play_screen_lock_choice), false);
SwitchPreference set_play_screen_lock_choice = findPreference(getString(R.string.set_play_screen_lock_choice));
assert set_play_screen_lock_choice != null;
set_play_screen_lock_choice.setChecked(playScreenLock);
//****** Display videos in a list *******
boolean videosInList = sharedpref.getBoolean(getString(R.string.set_video_in_list_choice), false);
SwitchPreference set_video_in_list_choice = findPreference(getString(R.string.set_video_in_list_choice));
assert set_video_in_list_choice != null;
set_video_in_list_choice.setChecked(videosInList);
//****** Language filter ********* //****** Language filter *********
LinkedHashMap<String, String> languages = new LinkedHashMap<>(peertubeInformation.getLanguages()); LinkedHashMap<String, String> languages = new LinkedHashMap<>(Helper.peertubeInformation.getLanguages());
List<CharSequence> entriesLanguages = new ArrayList<>(); List<CharSequence> entriesLanguages = new ArrayList<>();
List<CharSequence> valuesLanguages = new ArrayList<>(); List<CharSequence> valuesLanguages = new ArrayList<>();
Iterator<Map.Entry<String, String>> it = languages.entrySet().iterator(); Iterator<Map.Entry<String, String>> it = languages.entrySet().iterator();
@ -258,6 +411,31 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
if (selection != null) { if (selection != null) {
set_video_language_choice.setValues(selection); set_video_language_choice.setValues(selection);
} }
//****** Display sensitive content *******
ListPreference set_video_sensitive_choice = findPreference(getString(R.string.set_video_sensitive_choice));
List<String> arraySensitive = new ArrayList<>();
arraySensitive.add(getString(R.string.do_not_list));
arraySensitive.add(getString(R.string.blur));
arraySensitive.add(getString(R.string.display));
CharSequence[] entriesSensitive = arraySensitive.toArray(new CharSequence[0]);
CharSequence[] entryValuesSensitive = new CharSequence[3];
String currentSensitive = sharedpref.getString(getString(R.string.set_video_sensitive_choice), Helper.BLUR);
entryValuesSensitive[0] = Helper.DO_NOT_LIST.toLowerCase();
entryValuesSensitive[1] = Helper.BLUR.toLowerCase();
entryValuesSensitive[2] = Helper.DISPLAY.toLowerCase();
int currentSensitivePosition = 0;
for (CharSequence val : entryValuesSensitive) {
if (val.equals(currentSensitive)) {
break;
}
currentSensitivePosition++;
}
if (set_video_sensitive_choice != null) {
set_video_sensitive_choice.setEntries(entriesSensitive);
set_video_sensitive_choice.setEntryValues(entryValuesSensitive);
set_video_sensitive_choice.setValueIndex(currentSensitivePosition);
}
} }
} }

View File

@ -0,0 +1,45 @@
package app.fedilab.fedilabtube.helper;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import java.util.List;
import app.fedilab.fedilabtube.client.data.CommentData;
public class CommentDecorationHelper {
public static int getIndentation(String replyToCommentId, List<CommentData.Comment> comments) {
return numberOfIndentation(0, replyToCommentId, comments);
}
private static int numberOfIndentation(int currentIdentation, String replyToCommentId, List<CommentData.Comment> comments) {
String targetedComment = null;
for (CommentData.Comment comment : comments) {
if (replyToCommentId.compareTo(comment.getId()) == 0) {
targetedComment = comment.getInReplyToCommentId();
break;
}
}
if (targetedComment != null) {
currentIdentation++;
return numberOfIndentation(currentIdentation, targetedComment, comments);
} else {
return Math.min(currentIdentation, 15);
}
}
}

View File

@ -1,130 +0,0 @@
package app.fedilab.fedilabtube.helper;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.MediaController;
import androidx.core.content.res.ResourcesCompat;
import app.fedilab.fedilabtube.PeertubeActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.VideoData.Video;
/**
* Created by Thomas
* FullScreenMediaController. Inspired from the work at http://www.zoftino.com/android-videoview-playing-videos-full-screen
*/
public class FullScreenMediaController extends MediaController {
private final Context context;
private ImageButton fullScreen;
private Button resolution;
private Video peertube;
private String resolutionVal;
public FullScreenMediaController(Context context) {
super(context);
this.context = context;
}
@SuppressWarnings({"unused", "RedundantSuppression"})
public FullScreenMediaController(Context context, Video peertube) {
super(context);
this.peertube = peertube;
this.context = context;
}
@Override
public void setAnchorView(View view) {
super.setAnchorView(view);
//image button for full screen to be added to media controller
fullScreen = new ImageButton(context);
LayoutParams params =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.END;
params.rightMargin = 80;
params.topMargin = 22;
addView(fullScreen, params);
if (resolutionVal == null)
resolutionVal = peertube.getFiles().get(0).getResolutions().getLabel() + "p";
resolution = new Button(context);
resolution.setAllCaps(false);
resolution.setBackgroundColor(Color.TRANSPARENT);
resolution.setText(resolutionVal);
resolution.setPadding(0, 0, 0, 0);
LayoutParams paramsButton =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
paramsButton.gravity = Gravity.START;
paramsButton.rightMargin = 80;
paramsButton.topMargin = 22;
resolution.setOnClickListener(v -> ((PeertubeActivity) getContext()).displayResolution());
addView(resolution, paramsButton);
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
Resources resources = getResources();
fullScreen.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_baseline_fullscreen_exit_24, null));
} else {
Resources resources = getResources();
fullScreen.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_baseline_fullscreen_24, null));
}
//add listener to image button to handle full screen and exit full screen events
fullScreen.setOnClickListener(v -> {
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
((PeertubeActivity) getContext()).setFullscreen(fullscreen.OFF);
} else {
((PeertubeActivity) getContext()).setFullscreen(fullscreen.ON);
}
((PeertubeActivity) getContext()).change();
changeIcon();
});
}
@SuppressWarnings({"unused", "RedundantSuppression"})
public void setResolutionVal(String resolutionVal) {
this.resolutionVal = resolutionVal;
if (resolution != null)
resolution.setText(String.format("%sp", resolutionVal));
}
public void changeIcon() {
//fullscreen indicator from intent
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
Resources resources = getResources();
fullScreen.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_baseline_fullscreen_exit_24, null));
} else {
Resources resources = getResources();
fullScreen.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_baseline_fullscreen_24, null));
}
}
public enum fullscreen {
OFF,
ON
}
}

View File

@ -17,16 +17,20 @@ package app.fedilab.fedilabtube.helper;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.Parcelable;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View; import android.view.View;
@ -42,12 +46,16 @@ import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
import java.net.InetAddress;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -61,16 +69,19 @@ import app.fedilab.fedilabtube.client.data.AccountData.Account;
import app.fedilab.fedilabtube.client.data.ChannelData; import app.fedilab.fedilabtube.client.data.ChannelData;
import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.File; import app.fedilab.fedilabtube.client.entities.File;
import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
import app.fedilab.fedilabtube.sqlite.AccountDAO; import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.webview.CustomWebview; import app.fedilab.fedilabtube.webview.CustomWebview;
import app.fedilab.fedilabtube.webview.ProxyHelper; import app.fedilab.fedilabtube.webview.ProxyHelper;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import jp.wasabeef.glide.transformations.BlurTransformation;
import static android.content.Context.DOWNLOAD_SERVICE; import static android.content.Context.DOWNLOAD_SERVICE;
public class Helper { public class Helper {
public static PeertubeInformation peertubeInformation;
public static final int RELOAD_MYVIDEOS = 10; public static final int RELOAD_MYVIDEOS = 10;
public static final String SET_VIDEO_MODE = "set_video_mode"; public static final String SET_VIDEO_MODE = "set_video_mode";
public static final String SET_QUALITY_MODE = "set_quality_mode"; public static final String SET_QUALITY_MODE = "set_quality_mode";
@ -78,15 +89,21 @@ public class Helper {
public static final int LIGHT_MODE = 0; public static final int LIGHT_MODE = 0;
public static final int DARK_MODE = 1; public static final int DARK_MODE = 1;
public static final int DEFAULT_MODE = 2; public static final int DEFAULT_MODE = 2;
public static final String DO_NOT_LIST = "do_not_list";
public static final String BLUR = "blur";
public static final String DISPLAY = "display";
public static final String TIMELINE_TYPE = "timeline_type"; public static final String TIMELINE_TYPE = "timeline_type";
public static final int VIDEO_MODE_NORMAL = 0; public static final int VIDEO_MODE_NORMAL = 0;
public static final int VIDEO_MODE_STREAMING = 2; public static final int VIDEO_MODE_MAGNET = 2;
public static final int VIDEO_MODE_TORRENT = 3;
public static final int VIDEO_MODE_WEBVIEW = 1; public static final int VIDEO_MODE_WEBVIEW = 1;
public static final int QUALITY_HIGH = 0; public static final int QUALITY_HIGH = 0;
public static final int QUALITY_MEDIUM = 1; public static final int QUALITY_MEDIUM = 1;
public static final int QUALITY_LOW = 2; public static final int QUALITY_LOW = 2;
public static final int ADD_USER_INTENT = 5; public static final int ADD_USER_INTENT = 5;
public static final String SET_SHARE_DETAILS = "set_share_details"; public static final String SET_SHARE_DETAILS = "set_share_details";
public static final String NOTIFICATION_INTERVAL = "notification_interval";
public static final String LAST_NOTIFICATION_READ = "last_notification_read";
public static final int DEFAULT_VIDEO_CACHE_MB = 100; public static final int DEFAULT_VIDEO_CACHE_MB = 100;
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public static final String TAG = "mastodon_etalab"; public static final String TAG = "mastodon_etalab";
@ -113,7 +130,6 @@ public class Helper {
public static final String APP_PREFS = "app_prefs"; public static final String APP_PREFS = "app_prefs";
public static final int VIDEOS_PER_PAGE = 10; public static final int VIDEOS_PER_PAGE = 10;
public static final String INTENT_ADD_UPLOADED_MEDIA = "intent_add_uploaded_media";
public static final String RECEIVE_ACTION = "receive_action"; public static final String RECEIVE_ACTION = "receive_action";
public static final String SET_UNFOLLOW_VALIDATION = "set_unfollow_validation"; public static final String SET_UNFOLLOW_VALIDATION = "set_unfollow_validation";
//List of available academies //List of available academies
@ -431,16 +447,21 @@ public class Helper {
loadGiF(context, url, imageView, 10); loadGiF(context, url, imageView, 10);
} }
public static void loadGiF(final Context context, String instance, String url, final ImageView imageView, boolean blur) {
loadGif(context, instance, url, imageView, 10, blur);
}
public static void loadGiF(final Context context, String instance, String url, final ImageView imageView) { public static void loadGiF(final Context context, String instance, String url, final ImageView imageView) {
loadGif(context, instance, url, imageView, 10); loadGif(context, instance, url, imageView, 10, false);
} }
public static void loadGiF(final Context context, String url, final ImageView imageView, int round) { public static void loadGiF(final Context context, String url, final ImageView imageView, int round) {
loadGif(context, null, url, imageView, round); loadGif(context, null, url, imageView, round, false);
} }
@SuppressLint("CheckResult")
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private static void loadGif(final Context context, String instance, String url, final ImageView imageView, int round) { private static void loadGif(final Context context, String instance, String url, final ImageView imageView, int round, boolean blur) {
if (url == null || url.trim().toLowerCase().compareTo("null") == 0 || url.endsWith("null")) { if (url == null || url.trim().toLowerCase().compareTo("null") == 0 || url.endsWith("null")) {
Glide.with(imageView.getContext()) Glide.with(imageView.getContext())
.asDrawable() .asDrawable()
@ -456,11 +477,15 @@ public class Helper {
url = "https://" + url; url = "https://" + url;
} }
try { try {
Glide.with(imageView.getContext()) RequestBuilder<Drawable> requestBuilder = Glide.with(imageView.getContext())
.load(url) .load(url)
.thumbnail(0.1f) .thumbnail(0.1f);
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(round))) if (blur) {
.into(imageView); requestBuilder.apply(new RequestOptions().transform(new BlurTransformation(50, 3), new CenterCrop(), new RoundedCorners(10)));
} else {
requestBuilder.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(round)));
}
requestBuilder.into(imageView);
} catch (Exception e) { } catch (Exception e) {
try { try {
Glide.with(imageView.getContext()) Glide.with(imageView.getContext())
@ -603,6 +628,26 @@ public class Helper {
} }
/**
* Log out without removing user in db
*
* @param activity Activity
*/
public static void logoutNoRemoval(Activity activity) {
SharedPreferences sharedpreferences = activity.getSharedPreferences(APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(PREF_KEY_OAUTH_TOKEN, null);
editor.putString(CLIENT_ID, null);
editor.putString(CLIENT_SECRET, null);
editor.putString(PREF_KEY_ID, null);
editor.putString(ID, null);
editor.apply();
Intent loginActivity = new Intent(activity, MainActivity.class);
activity.startActivity(loginActivity);
activity.finish();
}
public static int getAttColor(Context context, int attColor) { public static int getAttColor(Context context, int attColor) {
TypedValue typedValue = new TypedValue(); TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(attColor, typedValue, true); context.getTheme().resolveAttribute(attColor, typedValue, true);
@ -661,6 +706,9 @@ public class Helper {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userName = sharedpreferences.getString(Helper.PREF_KEY_NAME, ""); String userName = sharedpreferences.getString(Helper.PREF_KEY_NAME, "");
String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, ""); String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, "");
if (video == null) {
return false;
}
Account account = video.getAccount(); Account account = video.getAccount();
ChannelData.Channel channel = video.getChannel(); ChannelData.Channel channel = video.getChannel();
if (account != null && instance != null && userName != null) { if (account != null && instance != null && userName != null) {
@ -687,7 +735,15 @@ public class Helper {
if (video_quality == QUALITY_HIGH) { if (video_quality == QUALITY_HIGH) {
return files.get(0); return files.get(0);
} else if (video_quality == QUALITY_LOW) { } else if (video_quality == QUALITY_LOW) {
return files.get(files.size() - 1); if (files.get(files.size() - 1).getResolutions().getLabel().trim().toLowerCase().compareTo("0p") != 0) {
return files.get(files.size() - 1);
} else {
if (files.size() > 1) {
return files.get(files.size() - 2);
} else {
return files.get(0);
}
}
} else { } else {
if (files.size() < 3) { if (files.size() < 3) {
return files.get(files.size() - 1); return files.get(files.size() - 1);
@ -697,4 +753,59 @@ public class Helper {
} }
} }
} }
/**
* Forward the intent (open an URL) to another app
*
* @param activity Activity
* @param i Intent
*/
public static void forwardToAnotherApp(Activity activity, Intent i) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(i.getData(), i.getType());
List<ResolveInfo> activities = activity.getPackageManager().queryIntentActivities(intent, 0);
ArrayList<Intent> targetIntents = new ArrayList<>();
String thisPackageName = activity.getPackageName();
for (ResolveInfo currentInfo : activities) {
String packageName = currentInfo.activityInfo.packageName;
if (!thisPackageName.equals(packageName)) {
Intent targetIntent = new Intent(android.content.Intent.ACTION_VIEW);
targetIntent.setDataAndType(intent.getData(), intent.getType());
targetIntent.setPackage(intent.getPackage());
targetIntent.setComponent(new ComponentName(packageName, currentInfo.activityInfo.name));
targetIntents.add(targetIntent);
}
}
if (targetIntents.size() > 0) {
Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), activity.getString(R.string.open_with));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
activity.startActivity(chooserIntent);
}
}
public static boolean instanceOnline(String host) {
try {
InetAddress ipAddr = InetAddress.getByName(host);
return ipAddr.toString().trim().compareTo("") != 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static String returnRoundedSize(Context context, long size) {
if (size == -1) {
return context.getString(R.string.unlimited);
} else if (size > 1000000000) {
float rounded = (float) size / 1000000000;
DecimalFormat df = new DecimalFormat("#.#");
return String.format(Locale.getDefault(), "%s%s", df.format(rounded), context.getString(R.string.gb));
} else {
float rounded = (float) size / 1000000;
DecimalFormat df = new DecimalFormat("#.#");
return String.format(Locale.getDefault(), "%s%s", df.format(rounded), context.getString(R.string.mb));
}
}
} }

View File

@ -0,0 +1,89 @@
package app.fedilab.fedilabtube.helper;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* 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.
*
* TubeLab 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 TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.RingtoneManager;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.AccountData;
import static app.fedilab.fedilabtube.worker.NotificationsWorker.FETCH_NOTIFICATION_CHANNEL_ID;
public class NotificationHelper {
/**
* Sends notification with intent
*
* @param context Context
* @param intent Intent associated to the notifcation
* @param icon Bitmap profile picture
* @param title String title of the notification
* @param message String message for the notification
*/
public static void notify_user(Context context, AccountData.Account account, Intent intent, Bitmap icon, String title, String message) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
int notificationId = (int) System.currentTimeMillis();
PendingIntent pIntent = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_ONE_SHOT);
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, FETCH_NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification_tubelab).setTicker(message)
.setWhen(System.currentTimeMillis());
notificationBuilder.setGroup(account.getAcct())
.setContentIntent(pIntent)
.setAutoCancel(true)
.setContentText(message);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
channel = new NotificationChannel(FETCH_NOTIFICATION_CHANNEL_ID, context.getString(R.string.fetch_notification_channel_name), NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
}
notificationBuilder.setContentTitle(title);
notificationBuilder.setLargeIcon(icon);
notificationManager.notify(notificationId, notificationBuilder.build());
Notification summaryNotification =
new NotificationCompat.Builder(context, FETCH_NOTIFICATION_CHANNEL_ID)
.setContentTitle(title)
.setContentText(context.getApplicationContext().getString(R.string.fetch_notification_channel_name))
.setContentIntent(pIntent)
.setLargeIcon(icon)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_notification_tubelab)
.setGroup(account.getAcct())
.setGroupSummary(true)
.build();
notificationManager.notify(0, summaryNotification);
}
}

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