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

636 Commits

Author SHA1 Message Date
Thomas
8f69d2295e New translations strings.xml (Dutch) 2022-07-20 17:02:39 +00:00
Thomas
08ec0d4657 New translations strings.xml (Dutch) 2022-07-20 12:48:27 +00:00
Thomas
adf54ec2a9 Release 1.15 2022-07-01 13:57:50 +02:00
Thomas
e19526dbf6 Release 1.15 2022-07-01 09:47:30 +02:00
Thomas
f6192881d3 Fixes 2022-07-01 09:44:00 +02:00
Thomas
309c6aa890 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!67
2022-07-01 07:41:54 +00:00
Thomas
9f6ac90074 New Crowdin updates 2022-07-01 07:41:54 +00:00
Thomas
8d4418bf2b Release 1.15.0 2022-07-01 08:43:47 +02:00
Thomas
3d85e74957 Fix playlist export/import 2022-06-03 11:41:26 +02:00
Thomas
fda17ee8fe Fix issue #21 - Prompt instances for avoiding default down ones 2022-05-30 11:06:24 +02:00
Thomas
5696809c1d fix manifest issues 2022-05-30 09:01:23 +02:00
Thomas
e03147c6da fix 2022-05-13 16:52:49 +02:00
Thomas
7c695f5f82 remove torrent lib 2022-05-13 16:41:58 +02:00
Thomas
1c6f7858ca some fixes 2022-05-13 14:11:11 +02:00
Thomas
1ef0389997 some fixes 2022-05-13 10:58:38 +02:00
Thomas
1c54d44a22 Some layout improvements 2022-05-12 17:46:08 +02:00
Thomas
724b43ca4d Some layout improvements 2022-05-12 15:12:18 +02:00
Thomas
ed3d978b03 Fix theme between flavors 2022-05-10 10:47:51 +02:00
Thomas
af53071b08 Fix authentication with openid 2022-05-10 10:19:45 +02:00
Thomas
bd8e2a50d9 Fix some color issues 2022-05-10 09:20:01 +02:00
Thomas
e5c918af51 Fix some color issues 2022-05-10 08:30:14 +02:00
Thomas
4077c5bc55 some cleaning 2022-05-10 08:06:32 +02:00
Thomas
2b43f32772 Fetch openId version 2022-05-09 12:03:49 +02:00
Thomas
1e0eafef9b Customize instances 2022-05-09 10:40:51 +02:00
Thomas
45b35d0718 Customize instances 2022-05-09 10:25:07 +02:00
Thomas
a9286ab150 theming 2022-05-05 10:08:04 +02:00
Thomas
fcb1974e78 theming 2022-05-05 08:53:25 +02:00
Thomas
2456e8f782 Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop
 Conflicts:
	app/build.gradle
	app/src/main/java/app/fedilab/fedilabtube/helper/HelperAcadInstance.java
2022-05-05 08:28:01 +02:00
Thomas
ce4913452b some upgrades 2022-05-04 09:43:54 +02:00
Thomas
e605dd8417 some upgrades 2022-05-03 15:10:37 +02:00
Thomas
8434f9ee00 change 2021-08-26 11:16:05 +02:00
Thomas
61bb7d962d remove flavor 2021-08-23 15:43:32 +02:00
Thomas
35aec32070 some changes 2021-05-02 18:59:05 +02:00
Thomas
274bcc8be7 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!66
2021-05-02 16:55:11 +00:00
Thomas
ce70df5137 New Crowdin updates 2021-05-02 16:55:11 +00:00
Thomas
d9dca3ef23 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!65
2021-01-29 17:04:22 +00:00
Thomas
e3635c3f01 New Crowdin updates 2021-01-29 18:04:21 +01:00
Thomas
2cdabbcb70 Release 1.13.1 2021-01-23 17:23:53 +01:00
Thomas
d5ad9b181b Release 1.13.1 2021-01-23 17:14:32 +01:00
Thomas
540fb3e2dc Update ReadMe remove useless accounts 2021-01-23 17:07:58 +01:00
Thomas
edbe65593b Some fixes 2021-01-23 17:03:26 +01:00
Thomas
d5f394dfea Fix issue with Manifest merging 2021-01-17 10:29:13 +01:00
Thomas
d5a5fdf52e Release 1.13.0 2021-01-16 18:25:59 +01:00
Thomas
a7f9256947 Small fixes 2021-01-16 14:14:15 +01:00
Thomas
d769729901 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!64
2021-01-16 11:34:44 +01:00
Thomas
b2026c8784 New Crowdin updates 2021-01-16 11:34:44 +01:00
Thomas
b29de141ef Add cast library for Google release only - Checked through Exodus 2021-01-16 11:33:59 +01:00
Thomas
6d4772da75 Fix issue #170 2021-01-11 17:42:54 +01:00
Thomas
2344fe0942 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!63
2021-01-09 18:47:38 +01:00
Thomas
7c309b68b8 New Crowdin updates 2021-01-09 18:47:38 +01:00
Thomas
c8c5e56a17 Cannot comment reply with Pleroma accounts 2021-01-09 18:47:08 +01:00
Thomas
cef227ba42 Release notes 2021-01-09 17:38:25 +01:00
Thomas
02296b038a Release 1.12.0 2021-01-09 17:33:53 +01:00
Thomas
b76a4cfcf5 Fix issue #160 #87 #88 - Notification counter + mark them all as read 2021-01-09 17:18:32 +01:00
Thomas
f168f101bc Fix issue #160 - Add a notification counter 2021-01-09 14:13:34 +01:00
Thomas
2e8a86fe20 Fix issue #160 - Move account item to make it visible in top bar 2021-01-09 10:52:34 +01:00
Thomas
fe0d2fe726 fix gradle issue 2021-01-09 10:48:11 +01:00
Thomas
9b322cc922 Fix issue #165 2021-01-09 10:42:37 +01:00
Thomas
346656e53d Fix issue #167 2021-01-09 09:21:26 +01:00
Thomas
6e6187175a Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!62
2021-01-08 18:08:28 +01:00
Thomas
5e832fa046 New Crowdin updates 2021-01-08 18:08:28 +01:00
Thomas
34007d4507 remove signingConfigs 2021-01-08 17:57:26 +01:00
Thomas
fd400f025e Merge branch 'donation_google' into develop
# Conflicts:
#	.gitignore
2021-01-08 17:45:00 +01:00
Thomas
f3f474ee13 Some fixes 2021-01-08 17:44:32 +01:00
Thomas
d971032d52 Some changes 2021-01-08 11:29:49 +01:00
Thomas
961c77103e Some changes 2021-01-08 11:18:01 +01:00
Thomas
b22b21c47a Some changes 2021-01-07 17:39:47 +01:00
Thomas
6d70bd758a Some changes 2021-01-06 19:23:44 +01:00
Thomas
087ac92f15 gitignore 2021-01-06 10:30:05 +01:00
Thomas
99fe789f30 Fix issue #164 & #156 2021-01-05 18:37:58 +01:00
Thomas
10892f92f1 Fix issue #162 2021-01-05 17:41:38 +01:00
Thomas
0a919c85ab Fix issue #163 2021-01-05 17:37:27 +01:00
Thomas
761abc013f Allow donation through Google 2021-01-05 17:26:21 +01:00
Thomas
327f6f0e8d Release notes 2021-01-03 16:06:15 +01:00
Thomas
d6f1a360d2 Release notes 2021-01-03 16:05:47 +01:00
Thomas
24ec69d7f7 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!61
2021-01-03 16:01:01 +01:00
Thomas
c80692bd34 New Crowdin updates 2021-01-03 16:01:00 +01:00
Thomas
b5e9f70be6 Allow to reblog/unreblog, favourite/unfavourite, bookmark/unbookmark videos from mastodon/pleroma Accounts 2021-01-03 12:10:34 +01:00
Thomas
d446081331 Small fix 2021-01-03 10:02:11 +01:00
Thomas
8178cff72c Small fix 2021-01-02 18:28:13 +01:00
Thomas
950d99b5de Prevent to check notifications for remote accounts 2021-01-02 18:20:36 +01:00
Thomas
b7855cb1a2 Working post comments from Mastodon/Pleroma 2021-01-02 18:09:09 +01:00
Thomas
b298fbfa3e Some changes 2021-01-02 13:38:58 +01:00
Thomas
d83929f80a Some changes 2021-01-02 11:21:30 +01:00
Thomas
b932ed2c13 Some fixes 2020-12-31 15:32:38 +01:00
Thomas
36073d340d Allow connection with Mastodon & Pleroma accounts 2020-12-31 14:19:26 +01:00
Thomas
0e14540b69 Allow connection of Mastodon & Pleroma accounts 2020-12-31 11:19:43 +01:00
Thomas
57327a8ad0 Check rights 2020-12-30 16:20:49 +01:00
Thomas
bbfa278d6b Implement logic 2020-12-30 15:37:09 +01:00
Thomas
439decf6a9 Merge remote-tracking branch 'origin/develop' into develop 2020-12-30 12:21:49 +01:00
Thomas
2277cc5f05 Some changes 2020-12-30 12:21:40 +01:00
Thomas
4204ffccee Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!60
2020-12-30 10:11:25 +01:00
Thomas
31407e709d New Crowdin updates 2020-12-30 10:11:25 +01:00
Thomas
44d26bb1cf Merge remote-tracking branch 'origin/develop' into develop 2020-12-29 17:11:56 +01:00
Thomas
8a8a433023 Some changes 2020-12-29 17:11:36 +01:00
Thomas
5c27292543 Fix #138 #155 2020-12-29 16:53:02 +01:00
Thomas
e475348d39 Some fixes 2020-12-29 09:55:15 +01:00
Thomas
9f8358e471 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!59
2020-12-28 17:36:02 +01:00
Thomas
4fd8d42d85 Some fixes 2020-12-28 15:43:59 +01:00
Thomas
498990c48a New translations strings.xml (French) 2020-12-28 15:43:37 +01:00
Thomas
1cddf26c9a Some fixes 2020-12-28 15:39:18 +01:00
Thomas
325a239b86 clean 2020-12-26 17:34:30 +01:00
Thomas
2c4ef9c3ce New translations strings.xml (Russian) 2020-12-25 20:06:50 +01:00
Thomas
4dbd191c4f Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!58
2020-12-25 10:33:12 +01:00
Thomas
01e489da10 New Crowdin updates 2020-12-25 10:33:12 +01:00
Thomas
53a7062c6d clean 2020-12-24 17:10:16 +01:00
Thomas
3425e1e593 Merge remote-tracking branch 'origin/develop' into develop 2020-12-24 16:40:35 +01:00
Thomas
9970635ff8 Fix issue #154 2020-12-24 16:40:18 +01:00
Thomas
c1f174a5b8 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!57
2020-12-24 15:32:59 +01:00
Thomas
3587e7c524 New Crowdin updates 2020-12-24 15:32:59 +01:00
Thomas
3911ad15a6 fix name 2020-12-24 12:01:59 +01:00
Thomas
d40b35da59 Fix issue #158 2020-12-24 11:57:27 +01:00
Thomas
ccb6e184cc Fix issue #151 2020-12-24 11:42:06 +01:00
Thomas
74e45b1820 Quick fix 2020-12-18 18:36:32 +01:00
Thomas
0a1336f0e0 Release 1.10.2 2020-12-18 18:00:47 +01:00
Thomas
d5a0dcb980 Fix issue #152 2020-12-18 16:49:18 +01:00
Thomas
83e7c41ca0 Merge branch 'l10n_develop' into develop 2020-12-18 16:35:05 +01:00
Thomas
1d1b0c11a9 fix CI 2020-12-18 14:41:48 +01:00
Thomas
3b2c4e2ac6 New translations strings.xml (Chinese Traditional) 2020-12-18 14:41:27 +01:00
Thomas
2d77fe580f New translations strings.xml (Chinese Simplified) 2020-12-18 14:41:23 +01:00
Thomas
7ae20f43f8 New translations strings.xml (Swedish) 2020-12-18 14:41:19 +01:00
Thomas
f03c1b206b New translations strings.xml (Russian) 2020-12-18 14:41:16 +01:00
Thomas
d99a58f2cf New translations strings.xml (Portuguese) 2020-12-18 14:41:12 +01:00
Thomas
5aeaf7f34b New translations strings.xml (Polish) 2020-12-18 14:41:09 +01:00
Thomas
af0b484d16 New translations strings.xml (Dutch) 2020-12-18 14:41:06 +01:00
Thomas
0a6791b752 New translations strings.xml (Korean) 2020-12-18 14:41:02 +01:00
Thomas
e73e306d05 New translations strings.xml (Japanese) 2020-12-18 14:40:58 +01:00
Thomas
52189abbff New translations strings.xml (Italian) 2020-12-18 14:40:53 +01:00
Thomas
d721f12d74 New translations strings.xml (Greek) 2020-12-18 14:40:49 +01:00
Thomas
69f28bb647 New translations strings.xml (German) 2020-12-18 14:40:45 +01:00
Thomas
2b2295d831 New translations strings.xml (Arabic) 2020-12-18 14:40:41 +01:00
Thomas
179586b8c4 New translations strings.xml (Spanish) 2020-12-18 14:40:38 +01:00
Thomas
1afad9e06a New translations strings.xml (French) 2020-12-18 14:40:35 +01:00
Thomas
59c73fd864 New translations strings.xml (Romanian) 2020-12-18 14:40:30 +01:00
Thomas
6820344750 Fix #145 and #153 2020-12-18 14:31:36 +01:00
Thomas
680504791c New translations strings.xml (Chinese Traditional) 2020-12-17 17:53:31 +01:00
Thomas
41e500a8f8 New translations strings.xml (Chinese Simplified) 2020-12-17 17:53:28 +01:00
Thomas
448af1ef9a New translations strings.xml (Swedish) 2020-12-17 17:53:23 +01:00
Thomas
041e8c0bd6 New translations strings.xml (Russian) 2020-12-17 17:53:19 +01:00
Thomas
0b7300e93a New translations strings.xml (Polish) 2020-12-17 17:53:16 +01:00
Thomas
94c5f5a705 New translations strings.xml (Dutch) 2020-12-17 17:53:12 +01:00
Thomas
fa2f8a7b05 New translations strings.xml (Korean) 2020-12-17 17:53:09 +01:00
Thomas
aeb288142e New translations strings.xml (Japanese) 2020-12-17 17:53:06 +01:00
Thomas
635c43f458 New translations strings.xml (Italian) 2020-12-17 17:53:03 +01:00
Thomas
d36138431b New translations strings.xml (Greek) 2020-12-17 17:52:58 +01:00
Thomas
9cdf857730 New translations strings.xml (German) 2020-12-17 17:52:55 +01:00
Thomas
52a6152af6 New translations strings.xml (Arabic) 2020-12-17 17:52:52 +01:00
Thomas
9d3312c081 New translations strings.xml (Spanish) 2020-12-17 17:52:48 +01:00
Thomas
1146236f46 New translations strings.xml (Portuguese) 2020-12-17 17:52:44 +01:00
Thomas
ec19ee1e55 New translations strings.xml (French) 2020-12-17 17:52:39 +01:00
Thomas
cc37e40158 New translations strings.xml (Romanian) 2020-12-17 17:52:05 +01:00
Thomas
bdd12de34d Fix issues #150 #149 #148 #147 2020-12-17 17:37:40 +01:00
Thomas
e64692d0d3 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!55
2020-12-17 14:37:10 +01:00
Thomas
7da8c0f664 New Crowdin updates 2020-12-17 14:37:10 +01:00
Thomas
fc41c077dc move fastlane 2020-12-17 14:16:49 +01:00
Thomas
50800da4b9 move fastlane 2020-12-17 14:01:35 +01:00
Thomas
a9219e8a91 move fastlane 2020-12-17 14:00:12 +01:00
Thomas
5eedadef47 New instance acad + matomo (acad flavor only) 2020-12-16 17:24:23 +01:00
Thomas
14cde8e625 Fixes 2020-12-16 10:14:46 +01:00
Thomas
1f2ecd591d Matomo for acad flavor 2020-12-14 16:41:29 +01:00
Thomas
9a2eb6cd49 Support openid 2020-12-14 14:42:28 +01:00
Thomas
aa38514bcb Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop 2020-12-14 08:27:49 +01:00
Thomas
f2fddfb16c typo 2020-12-13 15:41:26 +01:00
Thomas
05300682c1 Fixes 2020-12-13 15:41:00 +01:00
Thomas
a3714a4ecf Fix issue #143 2020-12-13 11:48:56 +01:00
Thomas
500584b9ef Fix some issues 2020-12-13 09:32:33 +01:00
Thomas
33ac822957 fix issue #142 2020-12-13 08:53:22 +01:00
Thomas
1f6107e238 Truncate long descriptions for instances with a way to expand them. 2020-12-12 15:41:28 +01:00
Thomas
2b7639599c Prepare release notes 2020-12-12 15:07:43 +01:00
Thomas
dedf7b0163 Fix issue #125 2020-12-12 14:58:28 +01:00
Thomas
88b5a83fb1 Fix issue #127 2020-12-12 14:47:59 +01:00
Thomas
efd6b0088f Fix issue #119 2020-12-12 14:45:14 +01:00
Thomas
ccb5cd20b1 Merge remote-tracking branch 'origin/develop' into develop 2020-12-12 14:39:29 +01:00
Thomas
668e41bc9b Fix issue #122 2020-12-12 14:39:20 +01:00
Thomas
46123fa7d6 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!54
2020-12-12 14:34:48 +01:00
Thomas
b079965de8 New Crowdin updates 2020-12-12 14:34:47 +01:00
Thomas
842ab914a4 Reverse to Fastlane with Flavors 2020-12-12 14:17:29 +01:00
Thomas
fcb93b7dc6 update details 2020-12-12 09:32:55 +01:00
Thomas
f1420fe29e Create flavor 2020-12-11 18:37:35 +01:00
Thomas
23f8674adc Fix #136 - crash with download button and lives 2020-12-11 17:59:24 +01:00
Thomas
76a4aa5ae6 Fix #136 - crash with download button and lives 2020-12-11 17:16:29 +01:00
Thomas
85ffb4064b clean 2020-12-09 18:26:52 +01:00
Thomas
73c9e639b6 Some improvements with cast 2020-12-09 18:26:11 +01:00
Thomas
5172695784 some fixes 2020-12-09 15:45:54 +01:00
Thomas
fcc10f97b5 Fix issue #134 2020-12-06 17:15:04 +01:00
Thomas
0a12020fd8 Fix issue #129 2020-12-06 11:24:36 +01:00
Thomas
e9c10b17e0 Fix issue #124 - typo 2020-12-06 10:59:01 +01:00
Thomas
f4698f1312 Issue #133 - history not working in URL 2020-12-06 10:46:18 +01:00
Thomas
1690507a18 Issue #123 - a small fix 2020-12-05 18:48:41 +01:00
Thomas
fbeb87e29e Issue #123 - improve player 2020-12-05 18:41:07 +01:00
Thomas
de14e95e90 Issue #123 - Working cast 2020-12-05 17:28:25 +01:00
Thomas
35c5713b0a #123 - some tests 2020-12-05 14:01:08 +01:00
Thomas
413792087e #123 - some tests 2020-12-05 11:27:27 +01:00
Thomas
21c53d2b4d Add cast support #123 - try 2020-12-02 18:37:54 +01:00
Thomas
5757a8b1d8 Add cast support #123 2020-12-02 18:05:35 +01:00
Thomas
680bdf7bd2 Split code 2020-12-01 18:35:54 +01:00
Thomas
6911fbd124 Limits some actions 2020-12-01 16:09:14 +01:00
Thomas
9fdffc9709 svg 2020-11-29 12:00:04 +01:00
Thomas
0b722a5ecc Add flavors 2020-11-29 11:59:27 +01:00
Thomas
6ae42ffefe Allow to change thumbnail for Playlists 2020-11-28 17:56:16 +01:00
Thomas
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
Thomas
04c2b277ce New Crowdin updates 2020-11-28 16:48:55 +01:00
Thomas
962462ff84 Fix some bugs 2020-11-28 16:41:21 +01:00
Thomas
964b0f2690 Fix some bugs when playing 2020-11-28 14:54:47 +01:00
Thomas
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
Thomas
61c3735e57 New Crowdin updates 2020-11-28 10:40:16 +01:00
Thomas
b0e29c0ba4 Some fixes 2020-11-28 10:33:13 +01:00
Thomas
e7f55aace9 Fix issue #117 2020-11-28 10:26:20 +01:00
Thomas
2955206b07 Some improvements with nsfw dialog 2020-11-28 09:32:31 +01:00
Thomas
b59d97279d Fix issue #115 - Filter with remote accounts does not work 2020-11-28 09:20:44 +01:00
Thomas
7d9e299940 Update release notes 2020-11-27 19:00:57 +01:00
Thomas
e15252a0f8 Some fixes 2020-11-27 18:56:37 +01:00
Thomas
e0907f1dc8 Swipe to change timelines 2020-11-27 18:36:31 +01:00
Thomas
1107391c43 Fix a crash 2020-11-27 15:00:25 +01:00
Thomas
2500035c33 Fix issue #58 - Remove more option menu for other channels 2020-11-27 14:29:29 +01:00
Thomas
24ad4dbc0f Fix issue #58 - Allow to search channels 2020-11-27 14:06:42 +01:00
Thomas
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
Thomas
720c13fa2d add decoration 2020-11-27 11:38:36 +01:00
Thomas
a02b8b79c1 some tests 2020-11-26 14:16:44 +01:00
Thomas
c2f99e130d clean adapter for comment 2020-11-25 15:11:13 +01:00
Thomas
250aa03e9a some tries 2020-11-25 15:08:38 +01:00
Thomas
dd7d253a1b Fix orientation issues 2020-11-25 11:26:14 +01:00
Thomas
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
Thomas
60630cc4ea New Crowdin updates 2020-11-25 09:34:44 +01:00
Thomas
85164c18e9 Fix issue #99 2020-11-25 09:31:39 +01:00
Thomas
3634e5e232 Some fixes 2020-11-24 17:32:18 +01:00
Thomas
f7d44cb547 Some fixes 2020-11-24 13:50:06 +01:00
Thomas
85b89507db Fix issue #113 2020-11-23 18:37:26 +01:00
Thomas
7415b752cc Release 1.8.0 2020-11-22 17:03:18 +01:00
Thomas
0a52060223 Merge remote-tracking branch 'origin/develop' into develop 2020-11-22 16:46:11 +01:00
Thomas
1024b1e6f9 color fixes + update lib 2020-11-22 16:46:05 +01:00
Thomas
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
Thomas
bfa3ede06b New Crowdin updates 2020-11-22 16:44:55 +01:00
Thomas
c7f6cdc8c6 Fix indentation 2020-11-22 11:15:49 +01:00
Thomas
58f280d347 Fix issue #106 2020-11-22 11:15:31 +01:00
Thomas
0715824ae1 Fix issue #108 2020-11-22 11:04:46 +01:00
Thomas
5540c8cacc Fix issue #109 2020-11-22 10:59:30 +01:00
Thomas
14efbdd08f Some fixes 2020-11-21 18:54:54 +01:00
Thomas
7ceb04d548 Fix remote videos not playing 2020-11-21 18:51:30 +01:00
Thomas
e9608f63db Prepare release 1.8.0 2020-11-21 17:26:28 +01:00
Thomas
64e1c7ca81 Update release notes 2020-11-21 17:24:28 +01:00
Thomas
7823b30900 Merge remote-tracking branch 'origin/develop' into develop 2020-11-21 17:17:42 +01:00
Thomas
1e45e4454c Change profile picture for channels 2020-11-21 17:17:34 +01:00
Thomas
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
Thomas
30416837a9 New Crowdin updates 2020-11-21 14:17:16 +01:00
Thomas
363132d331 Fix 2020-11-21 11:06:26 +01:00
Thomas
ebc0d744ed Fix 2020-11-21 09:59:33 +01:00
Thomas
d685031ee8 Fix upload 2020-11-21 09:37:18 +01:00
Thomas
3ea012f62e Change lib 2020-11-20 18:48:29 +01:00
Thomas
9a06f5660b Some fixes 2020-11-20 15:03:06 +01:00
Thomas
dff76aada1 Some fixes 2020-11-20 08:58:28 +01:00
Thomas
50a9f8a1b0 Some improvements 2020-11-19 18:08:28 +01:00
Thomas
8ff3b81112 Some fixes 2020-11-19 12:00:39 +01:00
Thomas
38f73a5d60 Some fixes 2020-11-18 19:15:19 +01:00
Thomas
15f6835a0c Some fixes 2020-11-18 19:04:54 +01:00
Thomas
84e3264726 Some fixes 2020-11-18 18:15:45 +01:00
Thomas
dbd068d95f Some fixes 2020-11-18 17:24:18 +01:00
Thomas
acba219e44 Fix issue #85 2020-11-18 15:44:47 +01:00
Thomas
c8e7c23855 Fix issue #89 2020-11-18 15:07:22 +01:00
Thomas
f0ff8a6feb Some fixes with video menu 2020-11-18 10:09:29 +01:00
Thomas
91a1380fef Fix issue #91 2020-11-18 10:00:25 +01:00
Thomas
3351ef7d91 Fix issue #76 2020-11-17 18:49:43 +01:00
Thomas
564cda58a5 Merge remote-tracking branch 'origin/develop' into develop 2020-11-17 18:31:17 +01:00
Thomas
3233fe673d Some fixes 2020-11-17 18:30:56 +01:00
Thomas
8cc8b284ce Some fixes 2020-11-17 18:10:45 +01:00
Thomas
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
Thomas
8f361c605a New Crowdin updates 2020-11-17 17:55:51 +01:00
Thomas
9d599e8b57 some improvements 2020-11-17 17:47:10 +01:00
Thomas
9c676d8002 some improvements 2020-11-16 18:54:59 +01:00
Thomas
d3ffc32d9b Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop
 Conflicts:
	app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
	app/src/main/java/app/fedilab/fedilabtube/drawer/CommentListAdapter.java
	app/src/main/java/app/fedilab/fedilabtube/helper/CommentDecorationHelper.java
	app/src/main/res/layout/activity_peertube.xml
2020-11-16 08:24:35 +01:00
Thomas
8c95554d8e Fix issue #70 2020-11-15 18:09:14 +01:00
Thomas
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
Thomas
32990932ad New Crowdin updates 2020-11-15 11:49:34 +01:00
Thomas
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
Thomas
05eaa196b4 Prepare release 1.7.0 2020-11-15 11:34:18 +01:00
Thomas
2cd076bfb8 Comment issue #46 - Allow to delete history 2020-11-15 11:27:38 +01:00
Thomas
02cd267cae Fix issue #68 - Videos in unlisted playlists cannot be displayed 2020-11-15 09:54:55 +01:00
Thomas
21394cb585 New translations strings.xml (Polish) 2020-11-15 03:16:43 +01:00
Thomas
73cd48b94a Release 1.7.0 2020-11-14 19:13:59 +01:00
Thomas
ea2cf58e5f Merge remote-tracking branch 'origin/develop' into develop 2020-11-14 17:52:32 +01:00
Thomas
2f3e29b037 Improve comments 2020-11-14 17:52:17 +01:00
Thomas
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
Thomas
66afb3f4ee New Crowdin updates 2020-11-14 17:49:48 +01:00
Thomas
dad94d753d Remove lib 2020-11-14 17:19:37 +01:00
Thomas
1727bebf58 update release notes 2020-11-14 15:26:36 +01:00
Thomas
37576c69ce fixes 2020-11-14 15:22:48 +01:00
Thomas
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
Thomas
3a14abaf2e fixes 2020-11-14 15:18:16 +01:00
Thomas
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
Thomas
931fb30330 New Crowdin updates 2020-11-14 15:10:47 +01:00
Thomas
b893dc9c4f Merge remote-tracking branch 'origin/develop' into develop 2020-11-14 15:10:27 +01:00
Thomas
f6ddd99449 Last fixes 2020-11-14 15:09:52 +01:00
Thomas
ddcbbfe670 Last fixes 2020-11-14 15:05:44 +01:00
Thomas
0f7438fa54 Some fixes 2020-11-14 12:19:37 +01:00
Thomas
fbbab1db68 Some fixes 2020-11-14 09:50:48 +01:00
Thomas
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
Thomas
1bcbcec8b8 New Crowdin updates 2020-11-13 18:46:57 +01:00
Thomas
c3e475be6f Allow to export/import 2020-11-13 18:45:55 +01:00
Thomas
150a81adc6 Some fixes 2020-11-12 17:08:43 +01:00
Thomas
a984607ee8 Update release notes 2020-11-11 18:28:50 +01:00
Thomas
2bf929986e Change button 2020-11-11 15:47:42 +01:00
Thomas
860edec2e6 Follow remote accounts 2020-11-11 15:36:15 +01:00
Thomas
90cfcbb7ae Fix issue #67 - Reaching profile edition from the account activity 2020-11-11 11:36:01 +01:00
Thomas
c63048730f Fix issue #62 - Errors with pull to refresh 2020-11-11 11:13:29 +01:00
Thomas
55bbafdbb5 Fix issue #63 - Reach owner from channels 2020-11-11 10:42:40 +01:00
Thomas
0923a07e42 Fix issue #59 - Follow button from sepia search 2020-11-11 10:37:49 +01:00
Thomas
431c21e066 Last fixes 2020-11-11 10:34:28 +01:00
Thomas
17c84f6c37 Switch from accounts 2020-11-10 18:44:48 +01:00
Thomas
58f10d9372 Add the logic 2020-11-09 18:48:10 +01:00
Thomas
a6dfd842e3 improve comments 2020-11-09 15:49:29 +01:00
Thomas
dfdda7627f Release 1.6.0 2020-11-08 17:48:13 +01:00
Thomas
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
Thomas
4627de23b4 New Crowdin updates 2020-11-08 17:42:24 +01:00
Thomas
023ab2d4b2 Release 1.6.0 2020-11-08 17:42:01 +01:00
Thomas
2a375318ea fix issue link 2020-11-08 16:50:20 +01:00
Thomas
fee593d059 Fix issue #44 - Sync NSFW + add them in settings to apply them. 2020-11-08 16:45:38 +01:00
Thomas
fe3546e282 Fix issue #57 - Allow to share channel and account links 2020-11-08 10:43:27 +01:00
Thomas
b61b6868a6 Fix issue #55 - Honor downloads disabled 2020-11-08 10:27:40 +01:00
Thomas
2f8ecd1f3e Prepare release 2020-11-07 17:23:53 +01:00
Thomas
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
Thomas
43e2762d4d New Crowdin updates 2020-11-07 15:55:16 +01:00
Thomas
8ab237a957 Fix issue #47 - Seek to last known position 2020-11-07 15:51:38 +01:00
Thomas
ffa5d0883a Update release notes 2020-11-07 10:42:19 +01:00
Thomas
14f0a47f52 Fix issue #40 - Allow search to resolve peertube links 2020-11-07 10:38:30 +01:00
Thomas
4c1e466866 Fix issue #42 - Allow to display channels from playing video activity 2020-11-07 10:24:56 +01:00
Thomas
24c6f79b51 small fix 2020-11-07 10:17:45 +01:00
Thomas
8c958a2563 Fix issue #31 - Show more content when available (with a toggle button) 2020-11-07 10:09:58 +01:00
Thomas
02cc00780d Merge remote-tracking branch 'origin/develop' into develop 2020-11-07 09:43:14 +01:00
Thomas
d13cce3997 Fix issue #39 - Allow to display videos in smaller lists 2020-11-07 09:42:56 +01:00
Thomas
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
Thomas
00751cedab New Crowdin updates 2020-11-06 19:10:28 +01:00
Thomas
c4e85a7161 Some improvements 2020-11-06 19:09:37 +01:00
Thomas
253b61fb11 Fix issue #29 - Accept URL for instances 2020-11-06 18:52:29 +01:00
Thomas
54ffbe2e15 Fix issue #30 2020-11-06 18:40:55 +01:00
Thomas
86d9ba930c Useless translations 2020-11-06 18:22:56 +01:00
Thomas
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
Thomas
aaac1652e9 New Crowdin updates 2020-11-06 18:01:21 +01:00
Thomas
c8fc98ee71 Add torrent 2020-11-06 17:32:12 +01:00
Thomas
4457259dfd Update README.md 2020-11-05 18:03:21 +01:00
Thomas
6dbb11f6e9 Fix notification settings 2020-11-05 17:56:26 +01:00
Thomas
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
Thomas
4afd2ca341 New Crowdin updates 2020-11-05 17:53:29 +01:00
Thomas
0c048877e0 Some new features 2020-11-05 17:38:57 +01:00
Thomas
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
Thomas
79ca0ceb88 New Crowdin updates 2020-11-04 18:55:41 +01:00
Thomas
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
Thomas
685467266a New Crowdin updates 2020-11-04 18:40:31 +01:00
Thomas
599e53b10c Merge remote-tracking branch 'origin/develop' into develop 2020-11-04 18:40:21 +01:00
Thomas
029b8b57ae push notifications 2020-11-04 18:39:45 +01:00
Thomas
631264eb57 push notifications 2020-11-04 17:43:38 +01:00
Thomas
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
Thomas
59741e5979 New Crowdin updates 2020-11-03 07:32:14 +01:00
Thomas
0f38ad180a Allow to edit profile + profile picture 2020-11-01 18:34:53 +01:00
Thomas
fdc6e6e325 Allow to edit profile 2020-10-31 18:24:52 +01:00
Thomas
ed9e79496a Auto play video when ended 2020-10-31 10:37:17 +01:00
Thomas
4f909417f1 Fix issue #14 2020-10-30 16:21:56 +01:00
Thomas
aecb4034ad Fix issue #20 2020-10-30 14:45:37 +01:00
Thomas
f0335d96d2 Fix issue #18 2020-10-29 18:56:57 +01:00
Thomas
65f3886355 upgrade lib 2020-10-29 10:05:40 +01:00
Thomas
8e2f1fb8fe Merge remote-tracking branch 'origin/develop' into develop 2020-10-28 15:03:15 +01:00
Thomas
852cfee310 Fix double click for pausing and exit fullscreen 2020-10-28 15:03:07 +01:00
Thomas
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
Thomas
11e8135cbd New translations strings.xml (German) 2020-10-27 11:45:01 +01:00
Thomas
824c4e0cbb Comment #16 - Redirect to another app if the URL can't be open with TubeLab 2020-10-26 19:02:55 +01:00
Thomas
9af7934448 Fix issue #16 2020-10-26 14:38:51 +01:00
Thomas
4ffa027e8d Merge remote-tracking branch 'origin/develop' into develop 2020-10-25 17:40:27 +01:00
Thomas
7e8ab3359a Add CHANGELOG + CONTRIBUTING.md + issue_template.md + FUNDING.yml 2020-10-25 17:40:09 +01:00
Thomas
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
Thomas
5c098857bd New Crowdin updates 2020-10-25 09:40:17 +01:00
Thomas
7fece740af Merge remote-tracking branch 'origin/develop' into develop 2020-10-24 16:36:54 +02:00
Thomas
857ab65f93 Some improvements 2020-10-24 16:36:49 +02:00
Thomas
807655da5b Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!31
2020-10-24 15:57:05 +02:00
Thomas
a77f37e564 New Crowdin updates 2020-10-24 15:57:04 +02:00
Thomas
1194209c82 Fix #13 - #14 - #15 Settings for auto fullscreen/ disable auto playblack / pause videos in fullscreen with key back 2020-10-24 14:42:51 +02:00
Thomas
f31b6e9ac8 Fix mini video view not supported on some devices 2020-10-23 15:33:35 +02:00
Thomas
3353b7205b Fix issue #10 2020-10-22 08:57:51 +02:00
Thomas
0f995cc615 Fix issue #11 2020-10-21 18:43:56 +02:00
Thomas
7be0f72292 Release 1.5.1 2020-10-17 18:53:13 +02:00
Thomas
ffbe8877a8 Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop 2020-10-17 18:50:26 +02:00
Thomas
74feb7e8f0 Release 1.5.1 2020-10-17 18:50:20 +02:00
Thomas
cbaef4bcfe Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!30
2020-10-17 18:08:38 +02:00
Thomas
38a387a423 New Crowdin updates 2020-10-17 18:08:38 +02:00
Thomas
1092eefc76 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!29
2020-10-17 16:47:12 +02:00
Thomas
3615b43b97 New Crowdin updates 2020-10-17 16:47:11 +02:00
Thomas
e17c7fb01d Fix some crashes 2020-10-17 10:55:25 +02:00
Thomas
f3d69e19a0 Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop 2020-10-17 10:53:11 +02:00
Thomas
ea102eb485 Fix some crashes 2020-10-17 10:52:56 +02:00
Thomas
2e4c01ed62 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!28
2020-10-17 05:55:39 +02:00
Thomas
ed22892d10 New Crowdin updates 2020-10-17 05:55:39 +02:00
Thomas
017bd5a6a2 Release 1.5.0 2020-10-16 18:03:41 +02:00
Thomas
967f11ddb4 Release 1.5.0 2020-10-16 17:53:30 +02:00
Thomas
6b4abd019e typo 2020-10-16 17:43:18 +02:00
Thomas
8b66c4030f Some fixes 2020-10-16 17:41:07 +02:00
Thomas
34f058358e Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!27
2020-10-16 17:26:37 +02:00
Thomas
2bab907777 New Crowdin updates 2020-10-16 17:26:37 +02:00
Thomas
52e64b6d85 Fix issue #9 2020-10-16 17:25:52 +02:00
Thomas
9510678a9f Manage accounts 2020-10-16 17:03:07 +02:00
Thomas
b4e7c3f8e2 New fixes 2020-10-16 11:37:40 +02:00
Thomas
d800d2b10c Fix comment layout 2020-10-15 19:07:58 +02:00
Thomas
785b4949e6 Fix a register issue 2020-10-15 19:02:12 +02:00
Thomas
b79e17cb60 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!26
2020-10-15 18:59:22 +02:00
Thomas
19fcbeb4b9 New Crowdin updates 2020-10-15 18:59:22 +02:00
Thomas
ffb355d1a2 Add notifications for abuse reports 2020-10-15 18:59:08 +02:00
Thomas
43fd2945cc Some improvements 2020-10-15 18:37:50 +02:00
Thomas
d93c74a449 Reply to comments 2020-10-15 18:11:37 +02:00
Thomas
7a197993c9 Support Emoji and replies 2020-10-15 15:16:41 +02:00
Thomas
dc2a252dd5 Prepare the new layout. 2020-10-14 19:14:54 +02:00
Thomas
2c33f7a7f8 Prepare the new layout. 2020-10-14 19:11:53 +02:00
Thomas
24a8a0dc00 Some improvements 2020-10-14 16:39:27 +02:00
Thomas
b78894b33c Merge remote-tracking branch 'origin/develop' into develop 2020-10-14 16:06:24 +02:00
Thomas
2d33d7f970 Fix comment issue when posting 2020-10-14 16:06:17 +02:00
Thomas
8823eb74ba Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!25
2020-10-14 15:24:32 +02:00
Thomas
7f77b86272 New Crowdin updates 2020-10-14 15:24:32 +02:00
Thomas
2f773b2f0f Custom instances per country 2020-10-14 10:57:28 +02:00
Thomas
ca69a6e86d Code cleaning 2020-10-14 10:31:02 +02:00
Thomas
3e5cefbf24 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!24
2020-10-13 18:12:03 +02:00
Thomas
245ef64ebe New Crowdin updates 2020-10-13 18:12:03 +02:00
Thomas
a0ff454dd9 Some improvements 2020-10-13 18:11:53 +02:00
Thomas
fa6b1560f8 Prepare release 1.4.2 2020-10-13 17:57:35 +02:00
Thomas
518b5f617b Merge remote-tracking branch 'origin/develop' into develop 2020-10-13 17:50:57 +02:00
Thomas
7c4ce7701c some fixes 2020-10-13 17:50:52 +02:00
Thomas
0b6557f9c5 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!23
2020-10-13 16:36:10 +02:00
Thomas
a8e00d137a New Crowdin updates 2020-10-13 16:36:10 +02:00
Thomas
75d3f74e48 Merge remote-tracking branch 'origin/develop' into develop 2020-10-13 16:35:56 +02:00
Thomas
3866317597 some fixes 2020-10-13 16:35:51 +02:00
Thomas
10e904fe4a Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!22
2020-10-13 14:32:42 +02:00
Thomas
be655f6c2b New Crowdin updates 2020-10-13 14:32:42 +02:00
Thomas
676e540059 Dark/Light/Automatic theme 2020-10-13 14:30:08 +02:00
Thomas
87763a050c Merge remote-tracking branch 'origin/develop' into develop 2020-10-13 11:06:58 +02:00
Thomas
ab45c1f80c Fix some issues + check if video is federated for Sepia search 2020-10-13 11:04:35 +02:00
Thomas
ec5f2c7c45 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!21
2020-10-12 07:35:45 +02:00
Thomas
c4448f22b9 New Crowdin updates 2020-10-12 07:35:44 +02:00
Thomas
62af5c54aa Release 1.4.1 2020-10-11 17:21:45 +02:00
Thomas
5872f5c99f Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!20
2020-10-11 17:18:41 +02:00
Thomas
2b1a63e08b New Crowdin updates 2020-10-11 17:18:41 +02:00
Thomas
7b96cf32b3 App rater for Google Full version 2020-10-10 15:40:16 +02:00
Thomas
6108bd143c App rater for Google Full version 2020-10-10 15:33:25 +02:00
Thomas
0127b9bffa Censor videos having youtube + download in their title (Google Play release only). 2020-10-10 15:21:46 +02:00
Thomas
8dddfc5497 Last fixes 2020-10-10 15:05:39 +02:00
Thomas
bf119a5808 Fix strings 2020-10-10 11:52:57 +02:00
Thomas
89ade69c5f Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!19
2020-10-10 11:49:50 +02:00
Thomas
93eaec8544 Fix some elements 2020-10-10 11:49:18 +02:00
Thomas
ce984de339 New translations strings.xml (French) 2020-10-10 10:32:08 +02:00
Thomas
b089ae93e1 Refresh subscription 2020-10-10 10:28:45 +02:00
Thomas
fc95708a84 Merge remote-tracking branch 'origin/develop' into develop 2020-10-10 09:43:40 +02:00
Thomas
7262690999 Fix translations 2020-10-10 09:43:35 +02:00
Thomas
f818c74943 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!18
2020-10-10 09:38:05 +02:00
Thomas
d7c5a04965 New Crowdin updates 2020-10-10 09:38:05 +02:00
Thomas
257a00fa1e Some fixes 2020-10-10 09:37:44 +02:00
Thomas
23875a2ceb Fix channel filter for subscriptions 2020-10-10 09:25:00 +02:00
Thomas
3f1883fbbc Fix an issue with overlapping views 2020-10-09 19:14:20 +02:00
Thomas
c5269a3129 comment #5 - Some improvements 2020-10-09 18:37:54 +02:00
Thomas
056092ac71 comment #5 - Add searches 2020-10-09 18:22:05 +02:00
Thomas
fd7632f001 comment #5 - searches 2020-10-09 14:54:01 +02:00
Thomas
fb83a1927d comment #5 - prepare layouts 2020-10-09 10:19:46 +02:00
Thomas
641a616c96 Change readme + fix titles 2020-10-08 18:46:18 +02:00
Thomas
fc051d8d1d Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop 2020-10-08 18:44:30 +02:00
Thomas
b8bec4f357 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!17
2020-10-08 18:44:22 +02:00
Thomas
fe78c8bf7e New Crowdin updates 2020-10-08 18:44:21 +02:00
Thomas
42caaa9dc9 Fix titles 2020-10-08 18:35:35 +02:00
Thomas
74d6cb8041 Prepare release 1.3.0 2020-10-08 18:30:47 +02:00
Thomas
7678da2bb6 Change description + fix pagination 2020-10-08 18:13:04 +02:00
Thomas
e771153f35 Some changes 2020-10-08 17:16:42 +02:00
Thomas
e96b9f7f02 Some fixes 2020-10-08 16:21:14 +02:00
Thomas
0604ac9ba8 Merge remote-tracking branch 'origin/develop' into develop 2020-10-07 17:46:25 +02:00
Thomas
bd0c59a69e Improve menu for videos 2020-10-07 17:46:15 +02:00
Thomas
0a84b75518 typo error 2020-10-07 09:25:58 +02:00
Thomas
c4b49b58cf typo error 2020-10-07 09:25:41 +02:00
Thomas
afbb27896e Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!16
2020-10-07 08:53:17 +02:00
Thomas
e0ff6c0ac3 New Crowdin updates 2020-10-07 08:53:17 +02:00
Thomas
4d7c7e88bb typo error 2020-10-06 19:02:25 +02:00
Thomas
7eef023277 some fixes 2020-10-06 18:49:15 +02:00
Thomas
6a762a8fd6 some fixes 2020-10-06 17:11:25 +02:00
Thomas
752e3d50c1 some fixes 2020-10-06 16:05:34 +02:00
Thomas
8377f9bb8a Merge branch 'develop' into new_feature
# Conflicts:
#	app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeAdapter.java
#	app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java
2020-10-06 15:32:04 +02:00
Thomas
5ff06a29d2 Merge branch 'develop' of https://framagit.org/tom79/fedilab-tube into develop
 Conflicts:
	app/build.gradle
2020-10-06 15:30:53 +02:00
Thomas
50aeb075b1 test 2020-10-06 15:30:15 +02:00
Thomas
79ff617d67 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!15
2020-10-06 14:09:02 +02:00
Thomas
5de8524f2a New Crowdin updates 2020-10-06 14:09:02 +02:00
Thomas
6164ff9163 change versionCode 2020-10-05 14:43:18 +02:00
Thomas
6e8b304b63 Fix crashes 2020-10-05 14:34:22 +02:00
Thomas
3be0cd727f Fix crashes 2020-10-05 14:34:01 +02:00
Thomas
451dd53230 Merge remote-tracking branch 'origin/develop' into develop 2020-10-04 17:51:15 +02:00
Thomas
34c1222fbc Code clean 2020-10-04 17:51:09 +02:00
Thomas
ccf2fc877b Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!14
2020-10-04 17:26:04 +02:00
Thomas
10a496c299 New Crowdin updates 2020-10-04 17:26:04 +02:00
Thomas
ba1bfd1f9c Change loader 2020-10-04 17:25:08 +02:00
Thomas
b9622da6c6 Merge remote-tracking branch 'origin/develop' into develop 2020-10-04 14:01:11 +02:00
Thomas
b3e9100c2f Fix inverted strings 2020-10-04 13:53:07 +02:00
Thomas
fb0e87397d Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!13
2020-10-04 13:51:25 +02:00
Thomas
bed1bb634b New Crowdin updates 2020-10-04 13:51:25 +02:00
Thomas
4db288743e typo 2020-10-03 19:10:00 +02:00
Thomas
ba569b2d40 change version code 2020-10-03 19:04:02 +02:00
Thomas
c774dcee96 Last fixes 2020-10-03 18:37:34 +02:00
Thomas
48fe22c8db Merge remote-tracking branch 'origin/develop' into develop 2020-10-03 17:02:59 +02:00
Thomas
3f282c8116 Some fixes 2020-10-03 17:02:48 +02:00
Thomas
4f4cdd68b5 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!12
2020-10-03 17:01:54 +02:00
Thomas
9c350c922b New Crowdin updates 2020-10-03 17:01:53 +02:00
Thomas
8548777c50 some checks 2020-10-03 16:22:19 +02:00
Thomas
30d344987c Fix an issue 2020-10-03 13:41:33 +02:00
Thomas
80c8e1a356 Release notes 2020-10-03 11:54:18 +02:00
Thomas
8ce7eb386f Release 1.2.0 2020-10-03 11:44:00 +02:00
Thomas
c50a587250 Some improvements 2020-10-03 11:24:26 +02:00
Thomas
a8b17ce0b2 Add cache for videos 2020-10-03 10:59:31 +02:00
Thomas
731863ef6c Merge remote-tracking branch 'origin/develop' into develop 2020-10-03 09:08:41 +02:00
Thomas
04b8294022 Fix triple-t 2020-10-03 09:08:36 +02:00
Thomas
4937ff43e5 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!11
2020-10-03 08:18:02 +02:00
Thomas
1670867a1d New Crowdin updates 2020-10-03 08:18:02 +02:00
Thomas
5e947cd221 Beta release 2020-10-02 19:33:57 +02:00
Thomas
1f8c5cbc05 Fix strings 2020-10-02 19:31:00 +02:00
Thomas
c2ab7a3608 Some improvements 2020-10-02 19:29:00 +02:00
Thomas
d62ff6d18f some fixes 2020-10-02 18:22:19 +02:00
Thomas
92a0af8b36 Fix full screen 2020-10-02 15:23:36 +02:00
Thomas
34ed36f9ae Fix issue 2020-10-02 15:14:08 +02:00
Thomas
7777317eb8 Merge remote-tracking branch 'origin/develop' into develop 2020-10-02 07:09:01 +02:00
Thomas
4d53612adc Some fixes 2020-10-02 07:03:36 +02:00
Thomas
e08d9805f1 Some improvements 2020-10-01 17:42:03 +02:00
Thomas
cb5b7274fe Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!10
2020-10-01 16:47:48 +02:00
Thomas
db84cac8f0 New Crowdin updates 2020-10-01 16:47:47 +02:00
Thomas
b6769ca25f Fix upload 2020-09-29 17:48:12 +02:00
Thomas
70903578d1 upload+actions with retrofit 2020-09-29 17:42:15 +02:00
Thomas
07d8a39681 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!9
2020-09-28 07:18:09 +02:00
Thomas
7410467cd6 New Crowdin updates 2020-09-28 07:18:09 +02:00
Thomas
f21732f753 Refresh token 2020-09-27 18:33:51 +02:00
Thomas
9dca5fcd3b Fix authentication 2020-09-27 16:33:43 +02:00
Thomas
1bc99b3c46 Fix Playing 2020-09-27 14:12:06 +02:00
Thomas
a8a5028852 Fix OverviewVideo 2020-09-27 11:37:48 +02:00
Thomas
f5fa9944ad Change overview management 2020-09-27 11:11:39 +02:00
Thomas
3697917d2b Some fixes 2020-09-26 19:41:21 +02:00
Thomas
9f25405983 Some fixes 2020-09-26 19:36:10 +02:00
Thomas
9c476037ef Some fixes 2020-09-26 19:31:38 +02:00
Thomas
2044a85b58 Fix issue 2020-09-26 16:52:41 +02:00
Thomas
d878ac780c some changes 2020-09-26 16:46:51 +02:00
Thomas
55179c6955 some changes 2020-09-26 10:22:11 +02:00
Thomas
618384cccb Change classes 2020-09-25 18:58:04 +02:00
Thomas
0b84823f64 Release notes 2020-09-24 07:36:25 +02:00
Thomas
9361f6ca64 Fix date 2020-09-24 07:31:46 +02:00
Thomas
b81257c77c Release 1.1.1 2020-09-24 07:28:36 +02:00
Thomas
75e919adbc Merge remote-tracking branch 'origin/develop' into develop 2020-09-24 07:27:55 +02:00
Thomas
d946451b27 Fix issue #3 2020-09-24 07:27:41 +02:00
Thomas
2d960d4c55 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!8
2020-09-23 08:35:18 +02:00
Thomas
6f24030b86 New Crowdin updates 2020-09-23 08:35:17 +02:00
Thomas
ce7b0d4d7d Fix typo 2020-09-21 07:33:46 +02:00
Thomas
ed34917550 Fix typo 2020-09-21 07:33:26 +02:00
Thomas
18bd328814 Fix typo 2020-09-21 07:30:08 +02:00
Thomas
cf35a65edd Fix typo 2020-09-21 07:28:26 +02:00
Thomas
fe04f32aa1 Fixes 2020-09-20 18:46:11 +02:00
Thomas
36f5f73a47 Fixes 2020-09-20 18:35:43 +02:00
Thomas
cd5e23364d build apk 2020-09-20 18:23:20 +02:00
Thomas
8bd4a3f5d1 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!7
2020-09-20 16:14:41 +02:00
Thomas
4114e4c349 New Crowdin updates 2020-09-20 16:14:41 +02:00
Thomas
3993e4a67e Release 1.1.0 2020-09-20 16:13:50 +02:00
Thomas
c78af3ea1a Release 1.1.0 2020-09-20 16:12:20 +02:00
Thomas
132687366c Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!6
2020-09-20 15:32:26 +02:00
Thomas
667469c773 New Crowdin updates 2020-09-20 15:32:26 +02:00
Thomas
e78e7a6f97 Small fix 2020-09-20 15:31:56 +02:00
Thomas
a1790bf32d Filter languages 2020-09-20 15:14:48 +02:00
Thomas
7a8e2f32b4 Merge remote-tracking branch 'origin/develop' into develop 2020-09-20 12:16:30 +02:00
Thomas
1932913793 Add logic 2020-09-20 12:16:10 +02:00
Thomas
7c40060438 Add logic 2020-09-20 12:06:38 +02:00
Thomas
0c6c5c813f Prepares views 2020-09-20 11:07:28 +02:00
Thomas
786b80e25e Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!5
2020-09-20 09:36:52 +02:00
Thomas
4cc0729d77 New translations strings.xml (Italian) 2020-09-19 21:15:19 +02:00
Thomas
9f444d6d88 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!4
2020-09-19 18:24:26 +02:00
Thomas
700fe6c9e8 New Crowdin updates 2020-09-19 18:24:26 +02:00
Thomas
3c2b8cc699 release 1.1.0-a 2020-09-19 18:22:44 +02:00
Thomas
eef6b3d76c release 1.1.0-a 2020-09-19 18:19:59 +02:00
Thomas
0a7fab6883 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!3
2020-09-19 17:23:07 +02:00
Thomas
1f7fe1fc6f New Crowdin updates 2020-09-19 17:23:06 +02:00
Thomas
5bb395f2d3 disable MissingTranslation 2020-09-19 17:22:34 +02:00
Thomas
4d6cb47e6c some fixes 2020-09-19 16:50:20 +02:00
Thomas
f7f85a9dbb some fixes 2020-09-19 15:06:24 +02:00
Thomas
118c2175f5 Play Minimized video when app in background 2020-09-19 14:56:10 +02:00
Thomas
645c9fa240 Add crowdin link 2020-09-19 13:07:39 +02:00
Thomas
13baaccd81 allows username when logging in 2020-09-19 13:01:27 +02:00
Thomas
aaa8281da8 Merge branch 'l10n_develop' into 'develop'
New Crowdin updates

See merge request tom79/fedilab-tube!2
2020-09-19 11:10:48 +02:00
Thomas
8bcc7e8f58 New Crowdin updates 2020-09-19 11:10:48 +02:00
Thomas
8085ed6a95 crowdin.yml 2020-09-19 10:57:52 +02:00
Thomas
12d24f4a56 crowdin.yml 2020-09-19 10:57:44 +02:00
Thomas
fcf2fbdd86 crowdin.yml 2020-09-19 10:48:49 +02:00
Thomas
81a711ee4c Prepare release 1.1.0 2020-09-18 18:16:47 +02:00
Thomas
b68cb689ca Multi account 2020-09-18 18:10:04 +02:00
Thomas
b2f1bf2817 Some offline fixes 2020-09-18 16:08:52 +02:00
Thomas
7aab6fbba9 Update info via a service 2020-09-18 14:37:34 +02:00
Thomas
015a2f3289 Some fixes 2020-09-18 12:03:35 +02:00
Thomas
647c827ee4 Pickup instance when registering 2020-09-17 19:01:31 +02:00
Thomas
e503a5ec95 Small fixes 2020-09-17 18:37:44 +02:00
Thomas
11209a5334 Some fixes 2020-09-17 17:00:12 +02:00
Thomas
b23686ab64 picker layout 2020-09-17 07:28:52 +02:00
Thomas
7f4c6faa1d add checkbox for selecting categories 2020-09-16 19:02:04 +02:00
Thomas
33c7f12180 Open dialog 2020-09-16 17:27:07 +02:00
Thomas
106bacb4b1 Add logic 2020-09-16 16:21:03 +02:00
Thomas
d6c662434d About page 2020-09-16 15:48:27 +02:00
Thomas
3705657aec About page 2020-09-16 15:47:49 +02:00
Thomas
ea810fd61b About page 2020-09-16 14:07:44 +02:00
Thomas
2d32aa9a9b Change icons 2020-09-16 10:12:34 +02:00
Thomas
e672b207b6 update README.md 2020-09-16 09:19:40 +02:00
Thomas
68dfb1b980 changes 2020-09-15 18:58:12 +02:00
Thomas
6feedf5c24 changes 2020-09-15 18:47:26 +02:00
Thomas
c196d3aebe changes 2020-09-15 18:39:37 +02:00
Thomas
a87ec4ffa5 Some fixes 2020-09-15 16:07:05 +02:00
Thomas
3e694b8ac2 Triple-T 2020-09-14 16:45:07 +02:00
Thomas
26af939014 improve flavor 2020-09-14 15:53:31 +02:00
Thomas
f0eaceb8a4 apply flavors 2020-09-13 19:20:04 +02:00
Thomas
7827c97bf9 Merge branch 'master' into full_version 2020-09-13 15:25:59 +02:00
Thomas
31e87a18bb Release 1.0.5 2020-09-12 18:31:37 +02:00
Thomas
07546abb7e Fix instances picker selected item 2020-09-12 18:26:34 +02:00
Thomas
124e0d8505 Add close button to instances picker 2020-09-12 18:10:52 +02:00
Thomas
94b969c428 Fix issue case sensitive issue 2020-09-12 18:05:55 +02:00
Thomas
cb9f8605d5 Improve time for videos 2020-09-12 17:54:37 +02:00
Thomas
5660fb15e5 Fix channel update 2020-09-12 17:35:21 +02:00
Thomas
d02fdba671 Improve channel creation 2020-09-12 16:53:04 +02:00
Thomas
d8de74ce7a Merge branch 'develop' into 'master'
Add .gitlab-ci.yml

See merge request tom79/fedilab-tube!1
2020-09-12 14:25:44 +02:00
Thomas
2129727cc5 Add .gitlab-ci.yml 2020-09-12 14:25:44 +02:00
Thomas
119ad4884b orientation fix 2020-09-12 14:11:02 +02:00
Thomas
3617fb3229 change titles for create/edit playlist/channel 2020-09-12 12:33:23 +02:00
Thomas
b272a5b5f9 Fix delete playlist 2020-09-12 12:27:54 +02:00
Thomas
58404694e0 Don't use token when not necessary 2020-09-12 10:42:17 +02:00
Thomas
c4c745dbc0 Fix some crashes 2020-09-12 10:37:11 +02:00
Thomas
2f909d5ffa Fix some crashes 2020-09-12 10:19:49 +02:00
Thomas
c714e6a625 Allow to edit channel and playlists 2020-09-11 19:10:54 +02:00
Thomas
bb2c129762 Some fixes 2020-09-11 15:56:18 +02:00
Thomas
42b0574143 VM-v9 2020-09-11 11:50:26 +02:00
Thomas
df0b18f535 VM-v8 2020-09-10 15:56:33 +02:00
Thomas
e8427b883d Some fixes 2020-09-09 18:55:52 +02:00
Thomas
4027a8b725 Some fixes 2020-09-09 15:00:15 +02:00
Thomas
a1b816030a VM-v7 2020-09-08 15:54:07 +02:00
Thomas
8c7d1c692b VM-v6 2020-09-08 12:08:49 +02:00
Thomas
7588a48cb5 VM-v5 2020-09-08 10:11:11 +02:00
Thomas
014302c3a8 VM-v4 2020-09-07 16:57:00 +02:00
Thomas
f632aa4712 VM-v3 2020-09-07 15:03:22 +02:00
Thomas
81de1c1aa0 VM-v2 2020-09-07 14:14:36 +02:00
Thomas
d89c998a35 VM-v1 2020-09-07 11:16:17 +02:00
Thomas
4c83a14786 VM1 2020-09-07 11:15:43 +02:00
Thomas
43e6d0baeb Fix sensitive email with double queries if necessary 2020-09-06 20:42:18 +02:00
Thomas
88514c0669 change build.gradle 2020-09-06 20:41:36 +02:00
520 changed files with 44587 additions and 14959 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']

17
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: inactive
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@
.externalNativeBuild
.cxx
/app/release/
/app/fdroid_full/release/
/frostwire-jlibtorrent/

133
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,133 @@
# This file is a template, and might need editing before it works on your project.
# Read more about this script on this blog post https://about.gitlab.com/2018/10/24/setting-up-gitlab-ci-for-android-projects/, by Jason Lenny
# If you are interested in using Android with FastLane for publishing take a look at the Android-Fastlane template.
image: openjdk:8-jdk
variables:
# ANDROID_COMPILE_SDK is the version of Android you're compiling with.
# It should match compileSdkVersion.
ANDROID_COMPILE_SDK: "30"
# ANDROID_BUILD_TOOLS is the version of the Android build tools you are using.
# It should match buildToolsVersion.
ANDROID_BUILD_TOOLS: "30.0.2"
# It's what version of the command line tools we're going to download from the official site.
# Official Site-> https://developer.android.com/studio/index.html
# There, look down below at the cli tools only, sdk tools package is of format:
# commandlinetools-os_type-ANDROID_SDK_TOOLS_latest.zip
# when the script was last modified for latest compileSdkVersion, it was which is written down below
ANDROID_SDK_TOOLS: "6609375"
# Packages installation before running script
before_script:
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
# Setup path as android_home for moving/exporting the downloaded sdk into it
- export ANDROID_HOME="${PWD}/android-home"
# Create a new directory at specified location
- install -d $ANDROID_HOME
# Here we are installing androidSDK tools from official source,
# (the key thing here is the url from where you are downloading these sdk tool for command line, so please do note this url pattern there and here as well)
# after that unzipping those tools and
# then running a series of SDK manager commands to install necessary android SDK packages that'll allow the app to build
- wget --output-document=$ANDROID_HOME/cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip
# move to the archive at ANDROID_HOME
- pushd $ANDROID_HOME
- unzip -d cmdline-tools cmdline-tools.zip
- popd
- export PATH=$PATH:${ANDROID_HOME}/cmdline-tools/tools/bin/
# Nothing fancy here, just checking sdkManager version
- sdkmanager --version
# use yes to accept all licenses
- yes | sdkmanager --sdk_root=${ANDROID_HOME} --licenses || true
- sdkmanager --sdk_root=${ANDROID_HOME} "platforms;android-${ANDROID_COMPILE_SDK}"
- sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools"
- sdkmanager --sdk_root=${ANDROID_HOME} "build-tools;${ANDROID_BUILD_TOOLS}"
# Not necessary, but just for surity
- chmod +x ./gradle
stages:
- build
- build-and-test
- tag
.no-upload: &no-upload
stage: build-and-test
retry: 2
# Make Project
assembleDebug:
<<: *no-upload
cache:
key: "${CI_COMMIT_TAG}"
paths:
- app/build/outputs/apk/fdroid_acad/debug/app-fdroid_acad-debug.apk
- app/build/outputs/apk/fdroid_full/debug/app-fdroid_full-debug.apk
policy: push
script:
- ./gradlew assembleDebug
# Basic android and gradle stuff
# Check linting
lintfdroid_acadDebug:
interruptible: true
stage: build
script:
- ./gradlew -Pci --console=plain :app:lintfdroid_acadDebug -PbuildDir=lint
except:
- tags
lintFdroid_fullDebug:
interruptible: true
stage: build
script:
- ./gradlew -Pci --console=plain :app:lintFdroid_fullDebug -PbuildDir=lint
except:
- tags
## PROTECTED VARIABLES TO SET IN GITLAB:
# - GITLAB_API_TOKEN: token you create on Gitlab
# - NC_REMOTE_DIR: like https://YOUR_NEXTCLOUD/remote.php/dav/files/YOUR_USER/mastalab (no trailing slash)
# - NC_SHARE_URL: share the folder in Nextcloud with public link and put your public link here (no trailing slash)
# - NC_USER: nextcloud user
# - NC_PASSWORD: nextcloud password
## Protect all tags in Gitlab repo settings (do a wildcard, ie '*')
# For now, it uses the assembleDebug builds, you'll need to create a job in build-and-test to create the apks, with only: - tags and add except: - tags to assembleDebug (like in debugTests)
# In it, put something like this to get your signature key file:
# - curl -s --output signature.jsk -u "${NC_USER}:${NC_PASSWORD}" "https://YOUR_NEXTCLOUD/remote.php/dav/files/YOUR_USER/signature.jsk"
putApkOnTags:
image: hatsoftwares/curl-jq:latest
stage: tag
retry: 2
cache:
key: "${CI_COMMIT_TAG}"
paths:
- app/build/outputs/apk/fdroid_acad/debug/app-fdroid_acad-debug.apk
- app/build/outputs/apk/fdroid_full/debug/app-fdroid_full-debug.apk
policy: pull
script:
- export PROJECT_API_URL="https://framagit.org/api/v4/projects/${CI_PROJECT_ID}"
- export DESCRIPTION_URL="${PROJECT_API_URL}/repository/tags/${CI_COMMIT_TAG}"
- export RELEASE_URL="${DESCRIPTION_URL}/release"
- export NC_UPLOAD_URL="${NC_REMOTE_DIR}/${CI_COMMIT_TAG}"
- export NC_DOWNLOAD_URL="${NC_SHARE_URL}/download?path=%2F${CI_COMMIT_TAG}%2F&files="
- 'export HEADER="Private-Token: ${GITLAB_API_TOKEN}"'
- export acadUrl="${NC_DOWNLOAD_URL}app-fdroid_acad-debug.apk"
- export fullUrl="${NC_DOWNLOAD_URL}app-fdroid_full-debug.apk"
- 'curl -s -u "${NC_USER}:${NC_PASSWORD}" -X MKCOL "${NC_UPLOAD_URL}"'
- 'curl -s -u "${NC_USER}:${NC_PASSWORD}" -T app/build/outputs/apk/fdroid_full/debug/app-fdroid_full-debug.apk "${NC_UPLOAD_URL}/app-fdroid_full-debug.apk"'
- 'curl -s -u "${NC_USER}:${NC_PASSWORD}" -T app/build/outputs/apk/fdroid_acad/debug/app-fdroid_acad-debug.apk "${NC_UPLOAD_URL}/app-fdroid_acad-debug.apk"'
- export description=$(curl -s --header "${HEADER}" "${DESCRIPTION_URL}" | jq .release.description | sed -e 's@"@@g')
- if [[ $description == 'null' ]]; then export METHOD="POST"; echo -e "[Get the acad version](${acadUrl})\n\n[Get the full version](${fullUrl})" > /tmp/text; fi
- if [[ $description != 'null' ]]; then export METHOD="PUT"; echo -e "${description}\n\n[Get the acad version](${acadUrl})\n\n[Get the full version](${fullUrl})" > /tmp/text; fi
- curl -s --request $METHOD --data-urlencode "description@/tmp/text" --header "${HEADER}" "${RELEASE_URL}"
only:
- tags

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 Framagit at: https://framagit.org/imattau/fedilab-tube/-/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

@@ -1,6 +1,46 @@
## TubeLab [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
## TubeLab/TubeAcad [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
This project groups two different apps. **[TubeAcad](#TubeAcad)**, a Peertube Android app for French academic authorities. All is in French. Its use is limited to some instances.
The other app is **[TubeLab](#TubeLab)** a Peertube Android app working for all instances.
## <a name="TubeLab">TubeLab</a>
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
It's a limited mode where you can do some actions:
- Switch instance
- Share videos
- Download videos
### Authenticated mode
Many features are available with this mode:
- Write/delete comments
- Upload/remove/edit videos
- Manage (create/edit/remove) channels and playlists
- Follow/unfollow channels
- Thumbs-up/down
- Check notifications
- Mute/unmute channels
- Report videos/accounts
- Check your history
## <a name="TubeAcad">TubeAcad</a>
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/)
TubeLab 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.
### Mode non authentifié
@@ -28,9 +68,3 @@ Si vous connectez votre compte, vous pourrez interagir avec les vidéos :
- Signaler des vidéos ou des comptes
- Voir l'historique
### Télécharger
[Fdroid](https://f-droid.org/packages/app.fedilab.fedilabtube/)
[GooglePlay](https://play.google.com/store/apps/details?id=app.fedilab.fedilabtube)

View File

@@ -1,23 +1,24 @@
apply plugin: 'com.android.application'
apply plugin: "androidx.navigation.safeargs"
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
compileSdkVersion 31
defaultConfig {
applicationId "app.fedilab.fedilabtube"
minSdkVersion 21
targetSdkVersion 30
versionCode 6
versionName "1.0.4"
targetSdkVersion 31
versionCode 45
versionName "1.15.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
dexOptions {
javaMaxHeapSize "4g"
}
flavorDimensions "default"
buildTypes {
release {
minifyEnabled false
@@ -28,6 +29,100 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
lintOptions {
disable 'MissingTranslation'
checkReleaseBuilds false
abortOnError false
}
//boolean full_instances if set to false means TubeAcad
productFlavors {
fdroid_acad {
applicationId "app.fedilab.fedilabtube"
resValue "string", "app_name", "TubeAcad"
resValue "string", "app_id", "app.fedilab.fedilabtube"
buildConfigField "String", "version", "\"fdroid_acad\""
buildConfigField "boolean", "full_instances", "false"
buildConfigField "boolean", "google_restriction", "false"
buildConfigField "boolean", "surfing_mode", "false"
buildConfigField "boolean", "sepia_search", "false"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "false"
buildConfigField "boolean", "google_cast_lib", "false"
buildConfigField "int", "cast_enabled", "0"
buildConfigField "int", "default_theme", "2"
}
google_acad {
applicationId "app.fedilab.fedilabtube"
resValue "string", "app_name", "TubeAcad"
resValue "string", "app_id", "app.fedilab.fedilabtube"
buildConfigField "String", "version", "\"google_acad\""
buildConfigField "boolean", "full_instances", "false"
buildConfigField "boolean", "google_restriction", "true"
buildConfigField "boolean", "surfing_mode", "false"
buildConfigField "boolean", "sepia_search", "false"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "false"
buildConfigField "boolean", "google_cast_lib", "true"
buildConfigField "int", "cast_enabled", "1"
buildConfigField "int", "default_theme", "2"
}
fdroid_full {
applicationId "app.fedilab.tubelab"
resValue "string", "app_name", "TubeLab"
resValue "string", "app_id", "app.fedilab.tubelab"
buildConfigField "String", "version", "\"fdroid_full\""
buildConfigField "boolean", "full_instances", "true"
buildConfigField "boolean", "google_restriction", "false"
buildConfigField "boolean", "surfing_mode", "true"
buildConfigField "boolean", "sepia_search", "true"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "true"
buildConfigField "boolean", "google_cast_lib", "false"
buildConfigField "int", "cast_enabled", "0"
buildConfigField "int", "default_theme", "2"
}
google_full {
applicationId "app.fedilab.tubelab"
resValue "string", "app_name", "TubeLab"
resValue "string", "app_id", "app.fedilab.tubelab"
buildConfigField "String", "version", "\"google_full\""
buildConfigField "boolean", "full_instances", "true"
buildConfigField "boolean", "google_restriction", "true"
buildConfigField "boolean", "surfing_mode", "true"
buildConfigField "boolean", "sepia_search", "true"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "true"
buildConfigField "boolean", "google_cast_lib", "true"
buildConfigField "int", "cast_enabled", "1"
buildConfigField "int", "default_theme", "2"
}
}
sourceSets {
fdroid_acad {
res.srcDirs = ['src/main/res', 'src/no_google_cast_lib/res', 'src/acad/res']
java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java', 'src/no_google_cast_lib/java']
}
google_acad {
res.srcDirs = ['src/main/res', 'src/google_cast_lib/res', 'src/acad/res']
java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java', 'src/google_cast_lib/java']
}
fdroid_full {
res.srcDirs = ['src/main/res', 'src/no_google_cast_lib/res', 'src/full/res']
java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java', 'src/no_google_cast_lib/java']
}
google_full {
res.srcDirs = ['src/main/res', 'src/google_donation/res', 'src/google_cast_lib/res', 'src/full/res']
java.srcDirs = ['src/main/java', 'src/full/java', 'src/google_donation/java', 'src/google_cast_lib/java']
}
}
}
allprojects {
@@ -37,33 +132,80 @@ allprojects {
}
}
dependencies {
implementation "androidx.multidex:multidex:2.0.1"
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation "androidx.fragment:fragment:1.2.5"
implementation 'androidx.navigation:navigation-ui:2.3.0'
implementation ("androidx.navigation:navigation-dynamic-features-fragment:2.3.0")
implementation 'androidx.navigation:navigation-fragment:2.4.2'
implementation "androidx.fragment:fragment:1.4.1"
implementation 'androidx.navigation:navigation-ui:2.4.2'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.browser:browser:1.2.0'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'androidx.browser:browser:1.4.0'
implementation 'androidx.documentfile:documentfile:1.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'com.github.GrenderG:Toasty:1.4.2'
implementation 'com.google.android.exoplayer:exoplayer:2.10.6'
implementation 'com.github.amoskorir:avatarimagegenerator:1.5.0'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
implementation 'com.github.GrenderG:Toasty:1.5.2'
implementation 'com.google.android.exoplayer:exoplayer:2.12.2'
implementation 'com.google.android.exoplayer:extension-mediasession:2.12.2'
implementation "com.github.mabbas007:TagsEditText:1.0.5"
implementation "com.github.bumptech.glide:glide:4.11.0"
annotationProcessor "com.github.bumptech.glide:compiler:4.11.0"
implementation 'jp.wasabeef:glide-transformations:4.0.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation 'org.apache.poi:poi:3.16'
implementation "net.gotev:uploadservice:3.5.2"
implementation "net.gotev:uploadservice-okhttp:3.5.2"
implementation "net.gotev:uploadservice:4.5.1"
implementation "net.gotev:uploadservice-okhttp:4.5.1"
implementation "com.google.code.gson:gson:2.8.6"
implementation 'androidx.media:media:1.6.0'
implementation 'com.github.ybq:Android-SpinKit:1.4.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
implementation "io.github.kobakei:ratethisapp:1.2.0"
implementation 'com.github.vkay94:DoubleTapPlayerView:1.0.0'
implementation "androidx.work:work-runtime:2.7.1"
//************ DONATION GOOGLE ONLY **************//
google_fullImplementation "com.android.billingclient:billing:4.1.0"
//************ MATOMO --> acad instances only **************//
fdroid_acadImplementation 'org.matomo.sdk:tracker:4.1.2'
google_acadImplementation 'org.matomo.sdk:tracker:4.1.2'
//************ CAST **************///
//---> Google libs (google_full)
google_acadImplementation "com.google.android.gms:play-services-cast-tv:19.0.1"
google_acadImplementation "com.google.android.gms:play-services-cast:21.0.1"
google_acadImplementation "androidx.mediarouter:mediarouter:1.3.0"
google_acadImplementation 'com.google.android.gms:play-services-cast-framework:21.0.1'
google_fullImplementation "com.google.android.gms:play-services-cast-tv:19.0.1"
google_fullImplementation "com.google.android.gms:play-services-cast:21.0.1"
google_fullImplementation "androidx.mediarouter:mediarouter:1.3.0"
google_fullImplementation 'com.google.android.gms:play-services-cast-framework:21.0.1'
//----> Other flavors
fdroid_acadImplementation 'su.litvak.chromecast:api-v2:0.11.3'
fdroid_acadImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
fdroid_acadImplementation 'org.slf4j:slf4j-simple:1.7.30'
fdroid_acadImplementation 'com.github.evozi:Cyanea:1.0.7'
fdroid_fullImplementation 'su.litvak.chromecast:api-v2:0.11.3'
fdroid_fullImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
fdroid_fullImplementation 'org.slf4j:slf4j-simple:1.7.30'
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,39 @@
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 org.matomo.sdk.Matomo;
import org.matomo.sdk.Tracker;
import org.matomo.sdk.TrackerBuilder;
public class FedilabTube extends BaseFedilabTube {
private Tracker mMatomoTracker;
@Override
public void onCreate() {
super.onCreate();
}
public synchronized Tracker getTracker() {
if (mMatomoTracker != null) return mMatomoTracker;
mMatomoTracker = TrackerBuilder.createDefault("https://wa.phm.education.gouv.fr/snp/matomo.php", 11).build(Matomo.getInstance(this));
return mMatomoTracker;
}
}

View File

@@ -0,0 +1,47 @@
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.app.Activity;
import android.content.Context;
import org.matomo.sdk.Tracker;
import org.matomo.sdk.extra.TrackHelper;
public class Matomo {
public static void sendScreen(Context _mcontext, String path, String title) {
Tracker tracker = ((FedilabTube) ((Activity) _mcontext).getApplication()).getTracker();
TrackHelper.track().screen(path).title(title).with(tracker);
}
public static void sendEvent(Context _mcontext, String category, String action, String label, float value) {
Tracker tracker = ((FedilabTube) ((Activity) _mcontext).getApplication()).getTracker();
TrackHelper.track().event(category, action).name(label).value(value).with(tracker);
}
public static void sendValue(Context _mcontext, String path, int index, String dimensionValue) {
Tracker tracker = ((FedilabTube) ((Activity) _mcontext).getApplication()).getTracker();
TrackHelper.track().screen(path).dimension(index, dimensionValue).with(tracker);
}
public static void trackInstall(Context _mcontext) {
Tracker tracker = ((FedilabTube) ((Activity) _mcontext).getApplication()).getTracker();
TrackHelper.track().download().with(tracker);
}
}

View File

@@ -1,5 +1,5 @@
package app.fedilab.fedilabtube.interfaces;
/* Copyright 2020 Thomas Schneider
package app.fedilab.fedilabtube.activities;
/* Copyright 2022 Thomas Schneider
*
* This file is a part of TubeLab
*
@@ -13,9 +13,15 @@ package app.fedilab.fedilabtube.interfaces;
*
* 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;
public interface OnDownloadInterface {
void onDownloaded(String saveFilePath, String downloadUrl, Error error);
import androidx.appcompat.app.AppCompatActivity;
void onUpdateProgress(int progress);
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}

View File

@@ -0,0 +1,59 @@
package app.fedilab.fedilabtube.helper;
/* Copyright 2022 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 androidx.appcompat.app.AppCompatActivity;
import app.fedilab.fedilabtube.R;
public class Theme {
public static void setTheme(AppCompatActivity activity, String instance, boolean noActionBar) {
switch (instance) {
case "tube-institutionnel.apps.education.fr":
activity.setTheme(noActionBar? R.style.InstitutionnelNoActionBar:R.style.Institutionnel);
break;
case "tube-maternelle.apps.education.fr":
activity.setTheme(noActionBar?R.style.MaternelleNoActionBar:R.style.Maternelle);
break;
case "tube-arts-lettres-sciences-humaines.apps.education.fr":
activity.setTheme(noActionBar?R.style.ArtNoActionBar:R.style.Art);
break;
case "tube-sciences-technologies.apps.education.fr":
activity.setTheme(noActionBar?R.style.SciencesNoActionBar:R.style.Sciences);
break;
case "tube-education-physique-et-sportive.apps.education.fr":
activity.setTheme(noActionBar?R.style.EducationNoActionBar:R.style.Education);
break;
case "tube-enseignement-professionnel.apps.education.fr":
activity.setTheme(noActionBar?R.style.EnseignementProNoActionBar:R.style.EnseignementPro);
break;
case "tube-langues-vivantes.apps.education.fr":
activity.setTheme(noActionBar?R.style.LanguesNoActionBar:R.style.Langues);
break;
case "tube-action-educative.apps.education.fr":
activity.setTheme(noActionBar?R.style.ActionEducativeNoActionBar:R.style.ActionEducative);
break;
case "tube-cycle-2.apps.education.fr":
activity.setTheme(noActionBar?R.style.Cycle2NoActionBar:R.style.Cycle2);
break;
case "tube-cycle-3.apps.education.fr":
activity.setTheme(noActionBar?R.style.Cycle3NoActionBar:R.style.Cycle3);
break;
default:
activity.setTheme(noActionBar?R.style.AppThemeNoActionBar:R.style.AppTheme);
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:color="@color/colorAccent"
android:state_checked="true" />
<item android:color="@android:color/tab_indicator_text" />
</selector>

View File

@@ -1,14 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:tint="#9C27B0"
android:viewportWidth="108"
android:viewportHeight="108">
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<group
android:scaleX="2.61"
android:scaleY="2.61"
android:translateX="22.68"
android:translateY="22.68">
android:scaleX="1.104"
android:scaleY="1.104"
android:translateX="-1.248"
android:translateY="-1.248">
<path
android:fillColor="@android:color/white"
android:pathData="M10,16.5l6,-4.5 -6,-4.5v9zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="2.0409248"
android:scaleY="2.0409248"
android:translateX="19.44"
android:translateY="19.44">
<path
android:fillColor="#502ca7"
android:pathData="m0,0h33.867v33.867h-33.867z" />
<path
android:fillColor="#9a26ae"
android:pathData="m15.544,29.459c-0.5613,-0.052 -1.8193,-0.2922 -2.5659,-0.49 -1.4544,-0.3854 -2.6614,-0.9423 -3.8833,-1.7918 -2.3102,-1.606 -3.8461,-3.928 -4.3943,-6.6437 -0.4789,-2.3721 -0.2362,-5.3562 0.6533,-8.0312 0.376,-1.131 0.7053,-1.8387 1.2806,-2.7519 0.9004,-1.4293 1.5877,-2.1804 2.8991,-3.1683 1.3049,-0.983 2.9258,-1.6476 4.88,-2.0009 0.8669,-0.1568 1.1303,-0.1748 2.5858,-0.1775 1.5249,-0.0027 1.6704,0.0078 2.465,0.1789 1.9969,0.43 3.3805,1.0324 4.9616,2.1602 1.8104,1.2913 3.1669,2.8519 4.0578,4.6681 0.896,1.8267 1.3075,3.6274 1.3075,5.7214 0,1.5759 -0.2607,3.1575 -0.7605,4.613 -0.8579,2.4986 -2.193,4.235 -4.4452,5.7811 -1.2142,0.8336 -2.9496,1.4792 -4.8751,1.8136 -0.6105,0.106 -3.4333,0.1862 -4.1663,0.1183zM19.42,26.9851c1.5946,-0.1757 3.0062,-0.5799 4.293,-1.2293 1.048,-0.5289 1.5517,-0.8781 2.271,-1.5743 0.9003,-0.8714 1.3979,-1.6179 1.8328,-2.7494 0.3399,-0.8845 0.4151,-1.1551 0.5267,-1.8953 0.3809,-2.5269 -0.4498,-6.1791 -1.8859,-8.291 -0.9544,-1.4038 -2.0586,-2.3755 -3.7036,-3.2592 -2.538,-1.3635 -6.6246,-1.6184 -9.6573,-0.6023 -1.2489,0.4185 -2.8043,1.4067 -3.6027,2.289 -0.7826,0.8649 -1.5925,2.2749 -1.9531,3.4007 -0.3872,1.2088 -0.4937,2.0043 -0.4947,3.695 -0.0008,1.3192 0.0189,1.6195 0.1484,2.2599 0.2029,1.0037 0.4086,1.6055 0.8491,2.4837 0.9265,1.8474 2.0961,3.1054 3.8624,4.1541 1.3723,0.8148 2.6611,1.2289 4.3987,1.4136 0.4192,0.0446 2.3964,-0.0157 3.1154,-0.0949z" />
<path
android:fillColor="#9a26ae"
android:pathData="m14.648,11.972 l7.4433,4.9609 -7.4433,4.9609z" />
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,145 @@
<resources>
<attr name="backgroundView" format="color" />
<style name="BaseTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
<item name="backgroundView">@color/backgroundDark</item>
</style>
<style name="BaseThemeNoAction" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="backgroundView">@color/backgroundDark</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="BaseTheme">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppThemeNoActionBar" parent="BaseThemeNoAction">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- Institutionnel theme. -->
<style name="Institutionnel" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_institutionnel</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_institutionnel</item>
<item name="colorAccent">@color/colorAccent_institutionnel</item>
</style>
<style name="InstitutionnelNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_institutionnel</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_institutionnel</item>
<item name="colorAccent">@color/colorAccent_institutionnel</item>
</style>
<!-- Maternelle theme. -->
<style name="Maternelle" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_maternelle</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_maternelle</item>
<item name="colorAccent">@color/colorAccent_maternelle</item>
</style>
<style name="MaternelleNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_maternelle</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_maternelle</item>
<item name="colorAccent">@color/colorAccent_maternelle</item>
</style>
<!-- Art theme. -->
<style name="Art" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_art</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_art</item>
<item name="colorAccent">@color/colorAccent_art</item>
</style>
<style name="ArtNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_art</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_art</item>
<item name="colorAccent">@color/colorAccent_art</item>
</style>
<!-- Sciences theme. -->
<style name="Sciences" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_sciences</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_sciences</item>
<item name="colorAccent">@color/colorAccent_sciences</item>
</style>
<style name="SciencesNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_sciences</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_sciences</item>
<item name="colorAccent">@color/colorAccent_sciences</item>
</style>
<!-- Education theme. -->
<style name="Education" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_education</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_education</item>
<item name="colorAccent">@color/colorAccent_education</item>
</style>
<style name="EducationNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_education</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_education</item>
<item name="colorAccent">@color/colorAccent_education</item>
</style>
<!-- Enseignement Pro theme. -->
<style name="EnseignementPro" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_enseignement_pro</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_enseignement_pro</item>
<item name="colorAccent">@color/colorAccent_enseignement_pro</item>
</style>
<style name="EnseignementProNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_enseignement_pro</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_enseignement_pro</item>
<item name="colorAccent">@color/colorAccent_enseignement_pro</item>
</style>
<!-- Langues theme. -->
<style name="Langues" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_langues</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_langues</item>
<item name="colorAccent">@color/colorAccent_langues</item>
</style>
<style name="LanguesNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_langues</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_langues</item>
<item name="colorAccent">@color/colorAccent_langues</item>
</style>
<!-- ActionEducative theme. -->
<style name="ActionEducative" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_action_educative</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_action_educative</item>
<item name="colorAccent">@color/colorAccent_action_educative</item>
</style>
<style name="ActionEducativeNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_action_educative</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_action_educative</item>
<item name="colorAccent">@color/colorAccent_action_educative</item>
</style>
<!-- Cycle 2 theme. -->
<style name="Cycle2" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_cycle2</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle2</item>
<item name="colorAccent">@color/colorAccent_cycle2</item>
</style>
<style name="Cycle2NoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_cycle2</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle2</item>
<item name="colorAccent">@color/colorAccent_cycle2</item>
</style>
<!-- Cycle 3 theme. -->
<style name="Cycle3" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_cycle3</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle3</item>
<item name="colorAccent">@color/colorAccent_cycle3</item>
</style>
<style name="Cycle3NoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_cycle3</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle3</item>
<item name="colorAccent">@color/colorAccent_cycle3</item>
</style>
<style name="theme" parent="@style/ThemeOverlay.AppCompat.Dark" />
<style name="popupTheme" parent="@style/ThemeOverlay.AppCompat.DayNight" />
<style name="progress" parent="SpinKitView.Circle" />
<style name="progressBottom" parent="SpinKitView.ThreeBounce" />
<style name="searchBarSepia" parent="MaterialSearchBarDark" />
</resources>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#512DA8</color>
<color name="colorPrimaryDark">#4527A0</color>
<color name="colorAccent">#9C27B0</color>
<!-- Institutionnel -->
<color name="colorPrimary_institutionnel">#1B2E35</color>
<color name="colorPrimaryDark_institutionnel">#1B2E35</color>
<color name="colorAccent_institutionnel">#35A8E0</color>
<!-- maternelle -->
<color name="colorPrimary_maternelle">#341047</color>
<color name="colorPrimaryDark_maternelle">#341047</color>
<color name="colorAccent_maternelle">#D3135D</color>
<!-- art -->
<color name="colorPrimary_art">#0d3b5f</color>
<color name="colorPrimaryDark_art">#0d3b5f</color>
<color name="colorAccent_art">#E61B72</color>
<!-- sciences -->
<color name="colorPrimary_sciences">#0d3b5f</color>
<color name="colorPrimaryDark_sciences">#0d3b5f</color>
<color name="colorAccent_sciences">#59b700</color>
<!-- education -->
<color name="colorPrimary_education">#0d3b5f</color>
<color name="colorPrimaryDark_education">#0d3b5f</color>
<color name="colorAccent_education">#EA3700</color>
<!-- enseignement pro -->
<color name="colorPrimary_enseignement_pro">#0d3b5f</color>
<color name="colorPrimaryDark_enseignement_pro">#0d3b5f</color>
<color name="colorAccent_enseignement_pro">#730FBA</color>
<!-- langues -->
<color name="colorPrimary_langues">#0d3b5f</color>
<color name="colorPrimaryDark_langues">#0d3b5f</color>
<color name="colorAccent_langues">#F69622</color>
<!-- Action éducative -->
<color name="colorPrimary_action_educative">#1B2E35</color>
<color name="colorPrimaryDark_action_educative">#1B2E35</color>
<color name="colorAccent_action_educative">#E52928</color>
<!-- cycle2 -->
<color name="colorPrimary_cycle2">#341047</color>
<color name="colorPrimaryDark_cycle2">#341047</color>
<color name="colorAccent_cycle2">#39A935</color>
<!-- cycle3 -->
<color name="colorPrimary_cycle3">#341047</color>
<color name="colorPrimaryDark_cycle3">#341047</color>
<color name="colorAccent_cycle3">#C1661B</color>
<color name="tag_color">#bbF2690D</color>
<color name="tag_color_text">#FAFAFA</color>
<color name="positive_thumbs">#2b90d9</color>
<color name="favorite">#ca8f04</color>
<color name="bookmark">#795548</color>
<color name="negative_thumbs">#F44336</color>
<color name="backgroundLight">#DDFFFFFF</color>
<color name="backgroundDark">#DD222222</color>
<color name="red_1">#F44336</color>
<color name="gray_light">#80808080</color>
</resources>

View File

@@ -0,0 +1,145 @@
<resources>
<attr name="backgroundView" format="color" />
<style name="BaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="backgroundView">@color/backgroundLight</item>
</style>
<style name="BaseThemeNoAction" parent="Theme.AppCompat.Light.NoActionBar">
<item name="backgroundView">@color/backgroundLight</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppThemeNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- Institutionnel theme. -->
<style name="Institutionnel" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_institutionnel</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_institutionnel</item>
<item name="colorAccent">@color/colorAccent_institutionnel</item>
</style>
<style name="InstitutionnelNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_institutionnel</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_institutionnel</item>
<item name="colorAccent">@color/colorAccent_institutionnel</item>
</style>
<!-- Maternelle theme. -->
<style name="Maternelle" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_maternelle</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_maternelle</item>
<item name="colorAccent">@color/colorAccent_maternelle</item>
</style>
<style name="MaternelleNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_maternelle</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_maternelle</item>
<item name="colorAccent">@color/colorAccent_maternelle</item>
</style>
<!-- Art theme. -->
<style name="Art" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_art</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_art</item>
<item name="colorAccent">@color/colorAccent_art</item>
</style>
<style name="ArtNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_art</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_art</item>
<item name="colorAccent">@color/colorAccent_art</item>
</style>
<!-- Sciences theme. -->
<style name="Sciences" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_sciences</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_sciences</item>
<item name="colorAccent">@color/colorAccent_sciences</item>
</style>
<style name="SciencesNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_sciences</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_sciences</item>
<item name="colorAccent">@color/colorAccent_sciences</item>
</style>
<!-- Education theme. -->
<style name="Education" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_education</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_education</item>
<item name="colorAccent">@color/colorAccent_education</item>
</style>
<style name="EducationNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_education</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_education</item>
<item name="colorAccent">@color/colorAccent_education</item>
</style>
<!-- Enseignement Pro theme. -->
<style name="EnseignementPro" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_enseignement_pro</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_enseignement_pro</item>
<item name="colorAccent">@color/colorAccent_enseignement_pro</item>
</style>
<style name="EnseignementProNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_enseignement_pro</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_enseignement_pro</item>
<item name="colorAccent">@color/colorAccent_enseignement_pro</item>
</style>
<!-- Langues theme. -->
<style name="Langues" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_langues</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_langues</item>
<item name="colorAccent">@color/colorAccent_langues</item>
</style>
<style name="LanguesNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_langues</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_langues</item>
<item name="colorAccent">@color/colorAccent_langues</item>
</style>
<!-- ActionEducative theme. -->
<style name="ActionEducative" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_action_educative</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_action_educative</item>
<item name="colorAccent">@color/colorAccent_action_educative</item>
</style>
<style name="ActionEducativeNoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_action_educative</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_action_educative</item>
<item name="colorAccent">@color/colorAccent_action_educative</item>
</style>
<!-- Cycle 2 theme. -->
<style name="Cycle2" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_cycle2</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle2</item>
<item name="colorAccent">@color/colorAccent_cycle2</item>
</style>
<style name="Cycle2NoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_cycle2</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle2</item>
<item name="colorAccent">@color/colorAccent_cycle2</item>
</style>
<!-- Cycle 3 theme. -->
<style name="Cycle3" parent="BaseTheme">
<item name="colorPrimary">@color/colorPrimary_cycle3</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle3</item>
<item name="colorAccent">@color/colorAccent_cycle3</item>
</style>
<style name="Cycle3NoActionBar" parent="BaseThemeNoAction">
<item name="colorPrimary">@color/colorPrimary_cycle3</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark_cycle3</item>
<item name="colorAccent">@color/colorAccent_cycle3</item>
</style>
<style name="theme" parent="@style/ThemeOverlay.AppCompat.Dark" />
<style name="popupTheme" parent="@style/ThemeOverlay.AppCompat.DayNight" />
<style name="progress" parent="SpinKitView.Circle" />
<style name="progressBottom" parent="SpinKitView.ThreeBounce" />
<style name="searchBarSepia" parent="MaterialSearchBarDark" />
</resources>

View File

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

View File

@@ -0,0 +1,39 @@
<?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=".activities.MainActivity"
tools:node="merge"
android:exported="true">
<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:host="*" />
<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=".activities.PeertubeActivity"
android:exported="true"
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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,4 +1,4 @@
package app.fedilab.fedilabtube.interfaces;
package app.fedilab.fedilabtube;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
@@ -14,8 +14,7 @@ package app.fedilab.fedilabtube.interfaces;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import app.fedilab.fedilabtube.client.APIResponse;
public interface OnRetrieveFeedsInterface {
void onRetrieveFeeds(APIResponse apiResponse);
}
public class FedilabTube extends BaseFedilabTube {
}

View File

@@ -14,22 +14,28 @@ package app.fedilab.fedilabtube;
* 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 androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;
import net.gotev.uploadservice.UploadService;
@SuppressWarnings({"unused", "RedundantSuppression"})
public class Matomo {
public class FedilabTube extends MultiDexApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
public static void sendScreen(Context _mcontext, String path, String title) {
//Do nothing
}
MultiDex.install(FedilabTube.this);
UploadService.NAMESPACE = BuildConfig.APPLICATION_ID;
public static void sendEvent(Context _mcontext, String category, String action, String label, float value) {
//Do nothing
}
}
public static void sendValue(Context _mcontext, String path, int index, String dimensionValue) {
//Do nothing
}
public static void trackInstall(Context _mcontext) {
//Do nothing
}
}

View File

@@ -1,5 +1,5 @@
package app.fedilab.fedilabtube.interfaces;
/* Copyright 2020 Thomas Schneider
package app.fedilab.fedilabtube.activities;
/* Copyright 2022 Thomas Schneider
*
* This file is a part of TubeLab
*
@@ -13,11 +13,14 @@ package app.fedilab.fedilabtube.interfaces;
*
* 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 java.util.List;
import androidx.appcompat.app.AppCompatActivity;
import app.fedilab.fedilabtube.client.entities.Status;
public class BaseActivity extends AppCompatActivity {
public interface OnRetrieveFeedsAccountInterface {
void onRetrieveFeedsAccount(List<Status> statuses);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}

View File

@@ -1,5 +1,5 @@
package app.fedilab.fedilabtube.interfaces;
/* Copyright 2020 Thomas Schneider
package app.fedilab.fedilabtube.helper;
/* Copyright 2022 Thomas Schneider
*
* This file is a part of TubeLab
*
@@ -13,13 +13,14 @@ package app.fedilab.fedilabtube.interfaces;
*
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import androidx.appcompat.app.AppCompatActivity;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.R;
public interface OnRetrievePeertubeInterface {
void onRetrievePeertube(APIResponse apiResponse);
public class Theme {
void onRetrievePeertubeComments(APIResponse apiResponse);
void onRetrievePeertubeChannels(APIResponse apiResponse);
@SuppressWarnings("unused")
public static void setTheme(AppCompatActivity activity, String instance, boolean noActionBar) {
activity.setTheme(noActionBar?R.style.AppThemeNoActionBar:R.style.AppTheme);
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorAccent" android:state_checked="true" />
<item android:color="@android:color/tab_indicator_text" />
</selector>

View File

@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<group
android:scaleX="1.104"
android:scaleY="1.104"
android:translateX="-1.248"
android:translateY="-1.248">
<path
android:fillColor="@android:color/white"
android:pathData="M10,16.5l6,-4.5 -6,-4.5v9zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z" />
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="2.0409248"
android:scaleY="2.0409248"
android:translateX="19.44"
android:translateY="19.44">
<path
android:fillColor="#000000"
android:pathData="m0,0h33.867v33.867h-33.867z" />
<path
android:fillColor="#f2690d"
android:pathData="m15.544,29.459c-0.5613,-0.052 -1.8193,-0.2922 -2.5659,-0.49 -1.4544,-0.3854 -2.6614,-0.9423 -3.8833,-1.7918 -2.3102,-1.606 -3.8461,-3.928 -4.3943,-6.6437 -0.4789,-2.3721 -0.2362,-5.3562 0.6533,-8.0312 0.376,-1.131 0.7053,-1.8387 1.2806,-2.7519 0.9004,-1.4293 1.5877,-2.1804 2.8991,-3.1683 1.3049,-0.983 2.9258,-1.6476 4.88,-2.0009 0.8669,-0.1568 1.1303,-0.1748 2.5858,-0.1775 1.5249,-0.0027 1.6704,0.0078 2.465,0.1789 1.9969,0.43 3.3805,1.0324 4.9616,2.1602 1.8104,1.2913 3.1669,2.8519 4.0578,4.6681 0.896,1.8267 1.3075,3.6274 1.3075,5.7214 0,1.5759 -0.2607,3.1575 -0.7605,4.613 -0.8579,2.4986 -2.193,4.235 -4.4452,5.7811 -1.2142,0.8336 -2.9496,1.4792 -4.8751,1.8136 -0.6105,0.106 -3.4333,0.1862 -4.1663,0.1183zM19.42,26.9851c1.5946,-0.1757 3.0062,-0.5799 4.293,-1.2293 1.048,-0.5289 1.5517,-0.8781 2.271,-1.5743 0.9003,-0.8714 1.3979,-1.6179 1.8328,-2.7494 0.3399,-0.8845 0.4151,-1.1551 0.5267,-1.8953 0.3809,-2.5269 -0.4498,-6.1791 -1.8859,-8.291 -0.9544,-1.4038 -2.0586,-2.3755 -3.7036,-3.2592 -2.538,-1.3635 -6.6246,-1.6184 -9.6573,-0.6023 -1.2489,0.4185 -2.8043,1.4067 -3.6027,2.289 -0.7826,0.8649 -1.5925,2.2749 -1.9531,3.4007 -0.3872,1.2088 -0.4937,2.0043 -0.4947,3.695 -0.0008,1.3192 0.0189,1.6195 0.1484,2.2599 0.2029,1.0037 0.4086,1.6055 0.8491,2.4837 0.9265,1.8474 2.0961,3.1054 3.8624,4.1541 1.3723,0.8148 2.6611,1.2289 4.3987,1.4136 0.4192,0.0446 2.3964,-0.0157 3.1154,-0.0949z" />
<path
android:fillColor="#f2690d"
android:pathData="m14.648,11.972 l7.4433,4.9609 -7.4433,4.9609z" />
</group>
</vector>

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -0,0 +1,39 @@
<resources>
<attr name="backgroundView" format="color" />
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">?attr/colorOnBackground</item>
<item name="backgroundView">@color/backgroundDark</item>
<item name="android:windowBackground">@android:color/black</item>
<item name="android:colorBackground">@android:color/black</item>
</style>
<style name="AppThemeNoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="backgroundView">@color/backgroundDark</item>
<item name="android:textColor">?attr/colorOnBackground</item>
<item name="android:windowBackground">@android:color/black</item>
<item name="android:colorBackground">@android:color/black</item>
</style>
<style name="theme" parent="@style/ThemeOverlay.AppCompat.Dark" />
<style name="popupTheme" parent="@style/ThemeOverlay.AppCompat.Dark" />
<style name="progress" parent="SpinKitView.Circle" />
<style name="progressBottom" parent="SpinKitView.ThreeBounce" />
<style name="searchBarSepia" parent="MaterialSearchBarDark" />
</resources>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#212529</color>
<color name="colorPrimaryDark">#000000</color>
<color name="colorAccent">#F2690D</color>
<color name="tag_color">#bbF2690D</color>
<color name="tag_color_text">#FAFAFA</color>
<color name="positive_thumbs">#2b90d9</color>
<color name="negative_thumbs">#F44336</color>
<color name="favorite">#ca8f04</color>
<color name="bookmark">#795548</color>
<color name="backgroundDark">#DD000000</color>
<color name="red_1">#F44336</color>
<color name="gray_light">#80808080</color>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#000000</color>
</resources>

View File

@@ -1,5 +1,5 @@
<resources>
<attr name="backgroundView" format="color" />
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
@@ -7,16 +7,27 @@
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">?attr/colorOnBackground</item>
<item name="backgroundView">@color/white</item>
</style>
<!-- Base application theme. -->
<style name="AppThemeNoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">?attr/colorOnBackground</item>
<item name="backgroundView">@color/white</item>
</style>
<style name="theme" parent="@style/ThemeOverlay.AppCompat.Dark" />
<style name="popupTheme" parent="@style/ThemeOverlay.AppCompat.Light" />
<style name="progress" parent="SpinKitView.Circle" />
<style name="progressBottom" parent="SpinKitView.ThreeBounce" />
<style name="searchBarSepia" parent="MaterialSearchBarLight" />
</resources>

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,41 @@
<?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=".activities.MainActivity"
tools:node="merge"
android:exported="true">
<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:host="*" />
<data android:mimeType="application/json" />
<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>
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="app.fedilab.fedilabtube.provider.CastOptionsProvider" />
</application>
</manifest>

View File

@@ -0,0 +1,42 @@
package app.fedilab.fedilabtube;
/* Copyright 2021 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.View;
import androidx.appcompat.app.AppCompatActivity;
import app.fedilab.fedilabtube.activities.BaseActivity;
import app.fedilab.fedilabtube.databinding.ActivityMainBinding;
public class BaseMainActivity extends BaseActivity {
protected ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
}
//Method for discovering cast devices
public void discoverCast() {
}
}

View File

@@ -0,0 +1,182 @@
package app.fedilab.fedilabtube;
/* Copyright 2021 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.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaMetadata;
import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.CastContext;
import com.google.android.gms.cast.framework.CastSession;
import com.google.android.gms.cast.framework.SessionManagerListener;
import com.google.android.gms.cast.framework.media.RemoteMediaClient;
import com.google.android.gms.common.images.WebImage;
import app.fedilab.fedilabtube.activities.BaseActivity;
import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.databinding.ActivityPeertubeBinding;
import app.fedilab.fedilabtube.helper.Helper;
public class BasePeertubeActivity extends BaseActivity {
protected ActivityPeertubeBinding binding;
protected VideoData.Video peertube;
protected SimpleExoPlayer player;
protected String videoURL;
protected String subtitlesStr;
private CastContext mCastContext;
private CastSession mCastSession;
private SessionManagerListener<CastSession> mSessionManagerListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityPeertubeBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int search_cast = sharedpreferences.getInt(getString(R.string.set_cast_choice), BuildConfig.cast_enabled);
if (search_cast == 1) {
setupCastListener();
mCastContext = CastContext.getSharedInstance(BasePeertubeActivity.this);
mCastSession = mCastContext.getSessionManager().getCurrentCastSession();
}
}
protected void loadCast() {
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
movieMetadata.putString(MediaMetadata.KEY_TITLE, peertube.getTitle());
movieMetadata.putString(MediaMetadata.KEY_ARTIST, peertube.getAccount().getDisplayName());
if (subtitlesStr != null) {
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, subtitlesStr);
}
movieMetadata.addImage(new WebImage(Uri.parse("https://" + peertube.getChannel().getHost() + peertube.getPreviewPath())));
MediaInfo mediaInfo = new MediaInfo.Builder(videoURL)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(movieMetadata)
.setStreamDuration(peertube.getDuration() * 1000L)
.build();
if (mCastSession != null) {
RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(mediaInfo);
}
}
private void setupCastListener() {
mSessionManagerListener = new SessionManagerListener<CastSession>() {
@Override
public void onSessionStarting(@NonNull CastSession castSession) {
}
@Override
public void onSessionStarted(@NonNull CastSession castSession, String s) {
onApplicationConnected(castSession, true);
}
@Override
public void onSessionStartFailed(@NonNull CastSession castSession, int i) {
onApplicationDisconnected();
}
@Override
public void onSessionEnding(@NonNull CastSession castSession) {
onApplicationDisconnected();
}
@Override
public void onSessionEnded(@NonNull CastSession castSession, int i) {
onApplicationDisconnected();
}
@Override
public void onSessionResuming(@NonNull CastSession castSession, String s) {
}
@Override
public void onSessionResumed(@NonNull CastSession castSession, boolean b) {
onApplicationConnected(castSession, false);
}
@Override
public void onSessionResumeFailed(@NonNull CastSession castSession, int i) {
onApplicationDisconnected();
}
@Override
public void onSessionSuspended(@NonNull CastSession castSession, int i) {
onApplicationDisconnected();
}
private void onApplicationConnected(CastSession castSession, boolean hide) {
mCastSession = castSession;
supportInvalidateOptionsMenu();
player.setPlayWhenReady(false);
if (hide) {
binding.doubleTapPlayerView.setVisibility(View.INVISIBLE);
}
binding.minController.castMiniController.setVisibility(View.VISIBLE);
loadCast();
}
private void onApplicationDisconnected() {
binding.doubleTapPlayerView.setVisibility(View.VISIBLE);
binding.minController.castMiniController.setVisibility(View.GONE);
supportInvalidateOptionsMenu();
}
};
}
@Override
protected void onResume() {
mCastContext.getSessionManager().addSessionManagerListener(
mSessionManagerListener, CastSession.class);
super.onResume();
}
@Override
protected void onPause() {
mCastContext.getSessionManager().removeSessionManagerListener(
mSessionManagerListener, CastSession.class);
super.onPause();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.video_menu, menu);
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
menu,
R.id.media_route_button);
return true;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 Google LLC. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.fedilab.fedilabtube.expandedcontrols;
import android.view.Menu;
import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity;
import app.fedilab.fedilabtube.R;
public class ExpandedControlsActivity extends ExpandedControllerActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.video_menu, menu);
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_button);
return true;
}
}

View File

@@ -0,0 +1,26 @@
package app.fedilab.fedilabtube.provider;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.android.gms.cast.framework.CastOptions;
import com.google.android.gms.cast.framework.OptionsProvider;
import com.google.android.gms.cast.framework.SessionProvider;
import java.util.List;
import app.fedilab.fedilabtube.helper.Helper;
public class CastOptionsProvider implements OptionsProvider {
@Override
public CastOptions getCastOptions(@NonNull Context context) {
return new CastOptions.Builder()
.setReceiverApplicationId(Helper.CAST_ID)
.build();
}
@Override
public List<SessionProvider> getAdditionalSessionProviders(@NonNull Context context) {
return null;
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/castMiniController"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:visibility="gone">
<fragment
class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/media_route_button"
android:title="@string/cast"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="always" />
</menu>

View File

@@ -0,0 +1,278 @@
package app.fedilab.fedilabtube;
/* Copyright 2021 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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
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.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetailsParams;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import app.fedilab.fedilabtube.databinding.ActivityDonationBinding;
import app.fedilab.fedilabtube.fragment.MySubscriptionDonationsFragment;
import app.fedilab.fedilabtube.fragment.DonationsFragment;
public class DonationActivity extends AppCompatActivity implements PurchasesUpdatedListener {
DonationsFragment donationsFragment;
DonationsFragment subscriptionDonationsFragment;
MySubscriptionDonationsFragment mySubscriptionDonationsFragment;
private ActivityDonationBinding binding;
private BillingClient billingClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDonationBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
billingClient = BillingClient.newBuilder(this)
.setListener(this)
.enablePendingPurchases()
.build();
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(@NotNull BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
donationsFragment.initialized(billingClient);
subscriptionDonationsFragment.initialized(billingClient);
List<Purchase> purchases = queryPurchases();
if (purchases != null) {
for (Purchase purchase : purchases) {
if (!purchase.isAutoRenewing()) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = (billingResult1, purchaseToken) -> {
//noinspection StatementWithEmptyBody
if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// Handle the success of the consume operation.
}
};
billingClient.consumeAsync(consumeParams, listener);
}
}
}
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
donationsFragment = new DonationsFragment();
Bundle bundle1 = new Bundle();
bundle1.putSerializable("isSubscriptions", false);
donationsFragment.setArguments(bundle1);
subscriptionDonationsFragment = new DonationsFragment();
Bundle bundle2 = new Bundle();
bundle2.putSerializable("isSubscriptions", true);
subscriptionDonationsFragment.setArguments(bundle2);
mySubscriptionDonationsFragment = new MySubscriptionDonationsFragment();
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.one_time)));
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.subscriptions)));
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.my_subscriptions)));
binding.viewpager.setOffscreenPageLimit(3);
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
binding.viewpager.setAdapter(mPagerAdapter);
binding.viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
TabLayout.Tab tab = binding.tablayout.getTabAt(position);
if (tab != null)
tab.select();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
binding.tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
binding.viewpager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private List<Purchase> queryPurchases() {
Purchase.PurchasesResult purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.SUBS);
List<Purchase> purchases = purchasesResult.getPurchasesList();
List<String> isSubscriptions = new ArrayList<>();
HashMap<String, Purchase> map = new HashMap<>();
if (purchases != null) {
for (Purchase purchase : purchases) {
try {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
JSONObject purchaseJson = new JSONObject(purchase.getOriginalJson());
String productId = purchaseJson.getString("productId");
isSubscriptions.add(productId);
map.put(productId, purchase);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
SkuDetailsParams.Builder paramsSub = SkuDetailsParams.newBuilder();
paramsSub.setSkusList(isSubscriptions).setType(BillingClient.SkuType.SUBS);
billingClient.querySkuDetailsAsync(paramsSub.build(),
(billingResult2, skuDetailsList) -> mySubscriptionDonationsFragment.initialized(skuDetailsList, map, billingClient));
} else {
mySubscriptionDonationsFragment.initialized(new ArrayList<>(), map, billingClient);
}
return purchases;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
String message;
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
if (!purchase.isAutoRenewing()) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = (billingResult1, purchaseToken) -> {
};
billingClient.consumeAsync(consumeParams, listener);
} else {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.acknowledgePurchase(acknowledgePurchaseParams, b -> {
});
}
}
queryPurchases();
}
}
message = getString(R.string.donation_succeeded_null);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
message = getString(R.string.donation_cancelled);
} else {
message = getString(R.string.toast_error);
}
View parentLayout = findViewById(android.R.id.content);
Snackbar snackbar = Snackbar.make(parentLayout, message, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.close, view -> snackbar.dismiss());
snackbar.show();
}
/**
* 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) {
if (position == 0) {
return donationsFragment;
} else if (position == 1) {
return subscriptionDonationsFragment;
} else {
return mySubscriptionDonationsFragment;
}
}
@Override
public int getCount() {
return 3;
}
}
}

View File

@@ -0,0 +1,91 @@
package app.fedilab.fedilabtube.drawable;
/* Copyright 2021 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.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.SkuDetails;
import java.util.List;
import java.util.Locale;
import app.fedilab.fedilabtube.DonationActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.databinding.DrawerDonationBinding;
public class DonationButtonAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<SkuDetails> skuDetails;
private final BillingClient billingClient;
private Context context;
private final boolean isSubscription;
public DonationButtonAdapter(List<SkuDetails> skuDetails, BillingClient billingClient, boolean subscription) {
this.isSubscription = subscription;
this.skuDetails = skuDetails;
this.billingClient = billingClient;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
DrawerDonationBinding itemBinding = DrawerDonationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
final ViewHolder holder = (ViewHolder) viewHolder;
SkuDetails skuDetail = skuDetails.get(position);
String currency = skuDetail.getPriceCurrencyCode();
String price = skuDetail.getPrice();
if (isSubscription) {
holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%s %s / %s", price, currency, context.getString(R.string.month)));
} else {
holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%s %s", price, currency));
}
holder.binding.buttonDonation.setOnClickListener(v -> {
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetail)
.build();
billingClient.launchBillingFlow((DonationActivity) context, billingFlowParams);
});
}
@Override
public int getItemCount() {
return skuDetails.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
DrawerDonationBinding binding;
ViewHolder(DrawerDonationBinding itemView) {
super(itemView.getRoot());
binding = itemView;
}
}
}

View File

@@ -0,0 +1,128 @@
package app.fedilab.fedilabtube.drawable;
/* Copyright 2021 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.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.SkuDetails;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.databinding.DrawerMyDonationBinding;
import es.dmoral.toasty.Toasty;
public class DonationHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<SkuDetails> skuDetailsList;
private final BillingClient billingClient;
private Context context;
private final HashMap<String, Purchase> map;
public DonationHistoryAdapter(List<SkuDetails> SkuDetailsList, HashMap<String, Purchase> map, BillingClient billingClient) {
this.skuDetailsList = SkuDetailsList;
this.billingClient = billingClient;
this.map = map;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
DrawerMyDonationBinding itemBinding = DrawerMyDonationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
final ViewHolder holder = (ViewHolder) viewHolder;
SkuDetails skuDetails = skuDetailsList.get(position);
holder.binding.productTitle.setText(skuDetails.getTitle());
holder.binding.productName.setText(skuDetails.getDescription());
holder.binding.productInfo.setText(skuDetails.getOriginalPrice());
holder.binding.cancelDonation.setOnClickListener(v -> {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setMessage(R.string.cancel_subscription_confirm);
dialogBuilder.setPositiveButton(R.string.cancel_subscription, (dialog, id) -> {
JSONObject skudetailsJson;
try {
skudetailsJson = new JSONObject(skuDetails.getOriginalJson());
String productId = skudetailsJson.getString("productId");
if (map.containsKey(productId)) {
Purchase purchase = map.get(productId);
if (purchase != null) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
ConsumeResponseListener listener = (billingResult1, purchaseToken) -> {
if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Toasty.success(context, context.getString(R.string.subscription_cancelled), Toasty.LENGTH_LONG).show();
}
skuDetailsList.remove(skuDetails);
notifyDataSetChanged();
};
billingClient.consumeAsync(consumeParams, listener);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
dialog.dismiss();
});
dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alertDialogLogoutAccount = dialogBuilder.create();
alertDialogLogoutAccount.show();
});
}
@Override
public int getItemCount() {
return skuDetailsList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
DrawerMyDonationBinding binding;
ViewHolder(DrawerMyDonationBinding itemView) {
super(itemView.getRoot());
binding = itemView;
}
}
}

View File

@@ -0,0 +1,112 @@
package app.fedilab.fedilabtube.fragment;
/* Copyright 2021 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.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.SkuDetailsParams;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.databinding.FragmentDonationsBinding;
import app.fedilab.fedilabtube.drawable.DonationButtonAdapter;
public class DonationsFragment extends Fragment {
public static final String[] donations = {"1", "2", "5", "10"};
private FragmentDonationsBinding binding;
private View rootView;
private Context context;
private boolean isSubscriptions;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentDonationsBinding.inflate(LayoutInflater.from(context));
rootView = binding.getRoot();
context = getContext();
Bundle bundle = this.getArguments();
if (bundle != null) {
isSubscriptions = bundle.getBoolean("isSubscriptions", false);
}
int donationText;
if (isSubscriptions) {
donationText = R.string.recurrent_donation_text;
} else {
donationText = R.string.one_time_donation_text;
}
binding.donationText.setText(donationText);
binding.loader.setVisibility(View.VISIBLE);
binding.lvProducts.setVisibility(View.GONE);
return rootView;
}
public void initialized(BillingClient bc) {
List<String> donationsList = new ArrayList<>();
for (String val : donations) {
donationsList.add("tubelab_donation_" + val + (isSubscriptions ? "_s" : ""));
}
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
if (isSubscriptions) {
params.setSkusList(donationsList).setType(BillingClient.SkuType.SUBS);
} else {
params.setSkusList(donationsList).setType(BillingClient.SkuType.INAPP);
}
bc.querySkuDetailsAsync(params.build(),
(billingResult, skuDetailsList) -> {
binding.loader.setVisibility(View.GONE);
binding.lvProducts.setVisibility(View.VISIBLE);
if (skuDetailsList != null) {
Collections.sort(skuDetailsList, (obj1, obj2) -> obj1.getPrice().compareTo(obj2.getPrice()));
}
DonationButtonAdapter donationButtonAdapter = new DonationButtonAdapter(skuDetailsList, bc, isSubscriptions);
binding.lvProducts.setAdapter(donationButtonAdapter);
binding.lvProducts.setLayoutManager(new LinearLayoutManager(context));
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
rootView = null;
}
@Override
public void onCreate(Bundle saveInstance) {
super.onCreate(saveInstance);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.context = context;
}
}

View File

@@ -0,0 +1,80 @@
package app.fedilab.fedilabtube.fragment;
/* Copyright 2021 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.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.SkuDetails;
import java.util.HashMap;
import java.util.List;
import app.fedilab.fedilabtube.databinding.FragmentMyDonationsBinding;
import app.fedilab.fedilabtube.drawable.DonationHistoryAdapter;
public class MySubscriptionDonationsFragment extends Fragment {
private FragmentMyDonationsBinding binding;
private View rootView;
private Context context;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentMyDonationsBinding.inflate(LayoutInflater.from(context));
rootView = binding.getRoot();
context = getContext();
binding.loader.setVisibility(View.VISIBLE);
binding.lvPurchases.setVisibility(View.GONE);
return rootView;
}
public void initialized(List<SkuDetails> skuDetailsList, HashMap<String, Purchase> map, BillingClient bc) {
binding.loader.setVisibility(View.GONE);
binding.lvPurchases.setVisibility(View.VISIBLE);
DonationHistoryAdapter donationHistoryAdapter = new DonationHistoryAdapter(skuDetailsList, map, bc);
binding.lvPurchases.setAdapter(donationHistoryAdapter);
binding.lvPurchases.setLayoutManager(new LinearLayoutManager(context));
}
@Override
public void onDestroyView() {
super.onDestroyView();
rootView = null;
}
@Override
public void onCreate(Bundle saveInstance) {
super.onCreate(saveInstance);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.context = context;
}
}

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2021 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>.
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activities.ShowChannelActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabSelectedTextColor="?colorAccent"
app:tabTextColor="@android:color/white" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button_donation"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingStart="40dp"
android:paddingTop="15dp"
android:paddingEnd="40dp"
android:paddingBottom="15dp"
android:textSize="25sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:id="@+id/product_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/cancel_donation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/product_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toStartOf="@+id/cancel_donation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/product_title" />
<TextView
android:id="@+id/product_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toStartOf="@+id/cancel_donation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/product_name" />
<ImageButton
android:id="@+id/cancel_donation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cancel"
android:src="@drawable/ic_baseline_delete_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2020 Thomas Schneider
Copyright 2021 Thomas Schneider
This file is a part of TubeLab
@@ -19,28 +19,27 @@
android:layout_height="match_parent"
android:paddingLeft="@dimen/fab_margin"
android:paddingRight="@dimen/fab_margin">
<!-- Listview Peertube bookmark -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
<RelativeLayout
android:id="@+id/no_action"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:gravity="center"
android:padding="10dp"
android:text="@string/bookmark_peertube_empty"
android:textSize="25sp" />
</RelativeLayout>
android:id="@+id/donation_text" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_products"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:scrollbars="none" />
</LinearLayout>
<!-- Main Loader -->
<RelativeLayout
android:id="@+id/loader"
@@ -49,10 +48,12 @@
android:gravity="center"
android:visibility="gone">
<ProgressBar
<com.github.ybq.android.spinkit.SpinKitView xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
android:layout_gravity="center"
app:SpinKit_Color="?colorAccent" />
</RelativeLayout>
</RelativeLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2020 Thomas Schneider
Copyright 2021 Thomas Schneider
This file is a part of TubeLab
@@ -19,38 +19,27 @@
android:layout_height="match_parent"
android:paddingLeft="@dimen/fab_margin"
android:paddingRight="@dimen/fab_margin">
<!-- Listview Accounts -->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeContainer"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:gravity="center"
android:text="@string/donations_description" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_accounts"
android:id="@+id/lv_purchases"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:scrollbars="none" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/no_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:id="@+id/no_action_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:padding="10dp"
android:text="@string/no_channels"
android:textSize="25sp"
android:textStyle="italic|bold"
android:typeface="serif" />
</RelativeLayout>
<!-- Main Loader -->
<RelativeLayout
android:id="@+id/loader"
@@ -59,25 +48,12 @@
android:gravity="center"
android:visibility="gone">
<ProgressBar
<com.github.ybq.android.spinkit.SpinKitView xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</RelativeLayout>
<!-- Loader for next accounts -->
<RelativeLayout
android:id="@+id/loading_next_accounts"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|center_horizontal"
android:gravity="bottom|center_horizontal"
android:visibility="gone">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:indeterminate="true" />
android:layout_gravity="center"
app:SpinKit_Color="?colorAccent" />
</RelativeLayout>
</RelativeLayout>

View File

@@ -0,0 +1,53 @@
<?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">
<uses-permission android:name="com.android.vending.BILLING" />
<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=".activities.PeertubeActivity"
android:exported="true"
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" />
<!-- 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>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.PeertubeActivity" />
</activity>
<activity
android:name=".expandedcontrols.ExpandedControlsActivity"
android:theme="@style/AppThemeNoActionBar"
/>
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="app.fedilab.fedilabtube.provider.CastOptionsProvider" />
<activity
android:name=".DonationActivity"
android:configChanges="orientation|screenSize"
android:label="@string/support_the_app"
android:windowSoftInputMode="stateAlwaysHidden" />
</application>
</manifest>

View File

@@ -5,19 +5,22 @@
<!--
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".FedilabTube"
android:allowBackup="false"
android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
@@ -25,95 +28,151 @@
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
android:name=".activities.MainActivity"
android:theme="@style/AppThemeNoActionBar"
android:configChanges="orientation|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".PeertubeActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name" />
android:name=".activities.PeertubeActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:launchMode="singleTask"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
tools:targetApi="n" />
<activity
android:name=".PeertubeEditUploadActivity"
android:name=".activities.PeertubeEditUploadActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".ShowAccountActivity"
android:name=".activities.ShowChannelActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".AccountActivity"
android:name=".activities.ShowAccountActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden"/>
<activity
android:name=".SearchActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".AllPlaylistsActivity"
android:name=".activities.AccountActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".PlaylistsActivity"
android:name=".activities.MyAccountActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".MyVideosActivity"
android:name=".activities.SearchActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".WebviewActivity"
android:name=".activities.AllPlaylistsActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.AllLocalPlaylistsActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.InstancePickerActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.PlaylistsActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.LocalPlaylistsActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.VideosTimelineActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.SepiaSearchActivity"
android:configChanges="orientation|screenSize"
android:label="@string/sepia_search"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.ManageInstancesActivity"
android:configChanges="orientation|screenSize"
android:label="@string/instances_picker"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.WebviewActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.WebviewConnectActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".activities.MastodonWebviewConnectActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name" />
/>
<activity
android:name=".WebviewConnectActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name" />
<activity
android:name=".LoginActivity"
android:name=".activities.LoginActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:windowSoftInputMode="stateAlwaysHidden">
android:windowSoftInputMode="stateAlwaysHidden"
android:exported="true">
<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:host="backtotubelab"
android:scheme="tubelab" />
</intent-filter>
</activity>
<activity
android:name=".SettingsActivity"
android:name=".activities.SettingsActivity"
android:configChanges="orientation|screenSize"
android:label="@string/settings"
android:windowSoftInputMode="stateAlwaysHidden">
</activity>
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".PeertubeRegisterActivity"
android:name=".activities.PeertubeRegisterActivity"
android:configChanges="orientation|screenSize"
android:label="@string/register_account"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".PeertubeUploadActivity"
android:name=".activities.PeertubeUploadActivity"
android:configChanges="orientation|screenSize"
android:label="@string/upload_video"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activities.AboutActivity"
android:configChanges="orientation|screenSize"
android:label="@string/about_the_app"
android:windowSoftInputMode="stateAlwaysHidden" />
<service
android:name=".services.RetrieveInfoService"
android:exported="false" />
<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>
<receiver
android:name=".services.PeertubeUploadReceiver"
android:exported="false">
<intent-filter>
<action android:name="app.fedilab.fedilabtube.uploadservice.broadcast.status" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1 @@
{"1":"Music","2":"Films","3":"Vehicles","4":"Art","5":"Sports","6":"Travels","7":"Gaming","8":"People","9":"Comedy","10":"Entertainment","11":"News & Politics","12":"How To","13":"Education","14":"Activism","15":"Science & Technology","16":"Animals","17":"Kids","18":"Food"}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
{"aa":"Afar","ab":"Abkhazian","af":"Afrikaans","ak":"Akan","am":"Amharic","ar":"Arabic","an":"Aragonese","ase":"American Sign Language","as":"Assamese","av":"Avaric","avk":"Kotava","ay":"Aymara","az":"Azerbaijani","ba":"Bashkir","bm":"Bambara","be":"Belarusian","bn":"Bengali","bfi":"British Sign Language","bi":"Bislama","bo":"Tibetan","bs":"Bosnian","br":"Breton","bg":"Bulgarian","bzs":"Brazilian Sign Language","ca":"Catalan","cs":"Czech","ch":"Chamorro","ce":"Chechen","cv":"Chuvash","kw":"Cornish","co":"Corsican","cr":"Cree","cse":"Czech Sign Language","csl":"Chinese Sign Language","cy":"Welsh","da":"Danish","de":"German","dv":"Dhivehi","dsl":"Danish Sign Language","dz":"Dzongkha","el":"Greek","en":"English","eo":"Esperanto","et":"Estonian","eu":"Basque","ee":"Ewe","fo":"Faroese","fa":"Persian","fj":"Fijian","fi":"Finnish","fr":"French","fy":"Western Frisian","fsl":"French Sign Language","ff":"Fulah","gd":"Scottish Gaelic","ga":"Irish","gl":"Galician","gv":"Manx","gn":"Guarani","gsg":"German Sign Language","gu":"Gujarati","ht":"Haitian","ha":"Hausa","sh":"Serbo-Croatian","he":"Hebrew","hz":"Herero","hi":"Hindi","ho":"Hiri Motu","hr":"Croatian","hu":"Hungarian","hy":"Armenian","ig":"Igbo","ii":"Sichuan Yi","iu":"Inuktitut","id":"Indonesian","ik":"Inupiaq","is":"Icelandic","it":"Italian","jv":"Javanese","jbo":"Lojban","ja":"Japanese","jsl":"Japanese Sign Language","kab":"Kabyle","kl":"Kalaallisut","kn":"Kannada","ks":"Kashmiri","ka":"Georgian","kr":"Kanuri","kk":"Kazakh","km":"Khmer","ki":"Kikuyu","rw":"Kinyarwanda","ky":"Kirghiz","kv":"Komi","kg":"Kongo","ko":"Korean","kj":"Kuanyama","ku":"Kurdish","lo":"Lao","la":"Latin","lv":"Latvian","li":"Limburgan","ln":"Lingala","lt":"Lithuanian","lb":"Luxembourgish","lu":"Luba-Katanga","lg":"Ganda","mh":"Marshallese","ml":"Malayalam","mr":"Marathi","mk":"Macedonian","mg":"Malagasy","mt":"Maltese","mn":"Mongolian","mi":"Maori","ms":"Malay (macrolanguage)","my":"Burmese","na":"Nauru","nv":"Navajo","nr":"South Ndebele","nd":"North Ndebele","ng":"Ndonga","ne":"Nepali (macrolanguage)","nl":"Dutch","nn":"Norwegian Nynorsk","nb":"Norwegian Bokmål","no":"Norwegian","ny":"Nyanja","oc":"Occitan","oj":"Ojibwa","or":"Oriya (macrolanguage)","om":"Oromo","os":"Ossetian","pa":"Panjabi","pks":"Pakistan Sign Language","pl":"Polish","pt":"Portuguese","ps":"Pushto","qu":"Quechua","rm":"Romansh","ro":"Romanian","rsl":"Russian Sign Language","rn":"Rundi","ru":"Russian","sg":"Sango","sdl":"Saudi Arabian Sign Language","sfs":"South African Sign Language","si":"Sinhala","sk":"Slovak","sl":"Slovenian","se":"Northern Sami","sm":"Samoan","sn":"Shona","sd":"Sindhi","so":"Somali","st":"Southern Sotho","es":"Spanish","sq":"Albanian","sc":"Sardinian","sr":"Serbian","ss":"Swati","su":"Sundanese","sw":"Swahili (macrolanguage)","sv":"Swedish","swl":"Swedish Sign Language","ty":"Tahitian","ta":"Tamil","tt":"Tatar","te":"Telugu","tg":"Tajik","tl":"Tagalog","th":"Thai","ti":"Tigrinya","tlh":"Klingon","to":"Tonga (Tonga Islands)","tn":"Tswana","ts":"Tsonga","tk":"Turkmen","tr":"Turkish","tw":"Twi","ug":"Uighur","uk":"Ukrainian","ur":"Urdu","uz":"Uzbek","ve":"Venda","vi":"Vietnamese","wa":"Walloon","wo":"Wolof","xh":"Xhosa","yi":"Yiddish","yo":"Yoruba","za":"Zhuang","zh":"Chinese","zu":"Zulu","zxx":"No linguistic content","zh-Hans":"Simplified Chinese","zh-Hant":"Traditional Chinese"}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,256 +0,0 @@
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.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
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.asynctasks.RetrieveAccountsAsyncTask;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment;
import app.fedilab.fedilabtube.fragment.DisplayNotificationsFragment;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
public class AccountActivity extends AppCompatActivity {
private ViewPager mPager;
private TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SpannableString content_create = new SpannableString(getString(R.string.join_peertube));
content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0);
content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(AccountActivity.this, R.color.colorAccent)), 0, content_create.length(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(AccountActivity.this);
TextView instanceView = findViewById(R.id.instance);
Account account = new AccountDAO(AccountActivity.this, db).getUniqAccount(userId, instance);
if (account == null) {
account = new AccountDAO(AccountActivity.this, db).getUniqAccount(userId, Helper.getPeertubeUrl(instance));
}
if (account == null) {
Helper.logoutCurrentUser(AccountActivity.this, null);
return;
}
ImageView profile_picture = findViewById(R.id.profile_picture);
TextView username = findViewById(R.id.username);
TextView displayname = findViewById(R.id.displayname);
setTitle(String.format("@%s", account.getUsername()));
Helper.loadGiF(AccountActivity.this, account, profile_picture);
username.setText(String.format("@%s", account.getUsername()));
displayname.setText(account.getDisplay_name());
instanceView.setText(account.getInstance());
Button logout_button = findViewById(R.id.logout_button);
Account finalAccount = account;
logout_button.setOnClickListener(v -> {
AlertDialog.Builder dialogBuilderLogoutAccount = new AlertDialog.Builder(AccountActivity.this);
dialogBuilderLogoutAccount.setMessage(getString(R.string.logout_account_confirmation, finalAccount.getUsername()));
dialogBuilderLogoutAccount.setPositiveButton(R.string.action_logout, (dialog, id) -> {
Helper.logoutCurrentUser(AccountActivity.this, finalAccount);
dialog.dismiss();
});
dialogBuilderLogoutAccount.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alertDialogLogoutAccount = dialogBuilderLogoutAccount.create();
alertDialogLogoutAccount.show();
});
Button settings = findViewById(R.id.settings);
settings.setOnClickListener(v -> {
Intent intent = new Intent(AccountActivity.this, SettingsActivity.class);
startActivity(intent);
});
tabLayout = findViewById(R.id.account_tabLayout);
mPager = findViewById(R.id.account_viewpager);
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.title_notifications)));
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.title_muted)));
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.title_channel)));
mPager.setOffscreenPageLimit(3);
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
TabLayout.Tab tab = tabLayout.getTabAt(position);
if (tab != null)
tab.select();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
mPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
Fragment fragment = null;
if (mPager.getAdapter() != null)
fragment = (Fragment) mPager.getAdapter().instantiateItem(mPager, tab.getPosition());
switch (tab.getPosition()) {
case 0:
if (fragment != null) {
DisplayNotificationsFragment displayNotificationsFragment = ((DisplayNotificationsFragment) fragment);
displayNotificationsFragment.scrollToTop();
}
break;
case 1:
case 2:
if (fragment != null) {
DisplayAccountsFragment displayAccountsFragment = ((DisplayAccountsFragment) fragment);
displayAccountsFragment.scrollToTop();
}
break;
}
}
});
PagerAdapter mPagerAdapter = new AccountsPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDestroy() {
super.onDestroy();
}
/**
* Pager adapter for three tabs (notifications, muted, blocked)
*/
private class AccountsPagerAdapter extends FragmentStatePagerAdapter {
AccountsPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NotNull
@Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
switch (position) {
case 1:
case 2:
DisplayAccountsFragment displayAccountsFragment = new DisplayAccountsFragment();
if (position == 1) {
bundle.putSerializable("accountFetch", RetrieveAccountsAsyncTask.accountFetch.MUTED);
} else {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(AccountActivity.this);
Account account = new AccountDAO(AccountActivity.this, db).getUniqAccount(userId, instance);
bundle.putString("name", account.getUsername() + "@" + account.getInstance());
bundle.putSerializable("accountFetch", RetrieveAccountsAsyncTask.accountFetch.CHANNEL);
}
displayAccountsFragment.setArguments(bundle);
return displayAccountsFragment;
default:
return new DisplayNotificationsFragment();
}
}
@Override
public int getCount() {
return 3;
}
}
}

View File

@@ -1,340 +0,0 @@
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.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.InputFilter;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
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 androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeChannelsAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.HttpsConnection;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Playlist;
import app.fedilab.fedilabtube.client.entities.PlaylistElement;
import app.fedilab.fedilabtube.drawer.PlaylistAdapter;
import app.fedilab.fedilabtube.interfaces.OnPlaylistActionInterface;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyncTask.peertubeInformation;
public class AllPlaylistsActivity extends AppCompatActivity implements OnPlaylistActionInterface, OnRetrievePeertubeInterface {
PlaylistAdapter playlistAdapter;
private AsyncTask<Void, Void, Void> asyncTask;
private RelativeLayout mainLoader;
private RelativeLayout textviewNoAction;
private HashMap<Integer, String> privacyToSend;
private Spinner set_upload_channel;
private Spinner set_upload_privacy;
private String idChannel;
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);
idChannel = null;
asyncTask = new ManagePlaylistsAsyncTask(AllPlaylistsActivity.this, ManagePlaylistsAsyncTask.action.GET_PLAYLIST, null, null, null, AllPlaylistsActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
FloatingActionButton add_new = findViewById(R.id.add_new);
LinkedHashMap<Integer, String> privaciesInit = new LinkedHashMap<>(peertubeInformation.getPrivacies());
if (privaciesInit.size() > 0) {
Map.Entry<Integer, String> entryInt = privaciesInit.entrySet().iterator().next();
privacyToSend = new HashMap<>();
privacyToSend.put(entryInt.getKey(), entryInt.getValue());
}
playlists = new ArrayList<>();
ListView lv_playlist = findViewById(R.id.lv_playlist);
playlistAdapter = new PlaylistAdapter(AllPlaylistsActivity.this, playlists, textviewNoAction);
lv_playlist.setAdapter(playlistAdapter);
add_new.setOnClickListener(view -> {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(AllPlaylistsActivity.this);
LayoutInflater inflater1 = getLayoutInflater();
View dialogView = inflater1.inflate(R.layout.add_playlist, new LinearLayout(AllPlaylistsActivity.this), false);
dialogBuilder.setView(dialogView);
EditText display_name = dialogView.findViewById(R.id.display_name);
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);
new RetrievePeertubeChannelsAsyncTask(AllPlaylistsActivity.this, AllPlaylistsActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
display_name.setFilters(new InputFilter[]{new InputFilter.LengthFilter(120)});
description.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1000)});
dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
if (display_name.getText() != null && display_name.getText().toString().trim().length() > 0) {
PlaylistElement playlistElement = new PlaylistElement();
playlistElement.setDisplayName(display_name.getText().toString().trim());
if (description.getText() != null && description.getText().toString().trim().length() > 0) {
playlistElement.setDescription(description.getText().toString().trim());
}
playlistElement.setVideoChannelId(idChannel);
String idPrivacy;
String label;
Map.Entry<Integer, String> privacyM = privacyToSend.entrySet().iterator().next();
idPrivacy = String.valueOf(privacyM.getKey());
label = privacyM.getValue();
if ((label.equals("Public") && (playlistElement.getVideoChannelId() == null || playlistElement.getVideoChannelId().equals("")))) {
Toasty.error(AllPlaylistsActivity.this, getString(R.string.error_channel_mandatory), Toast.LENGTH_LONG).show();
} else {
if (privacyToSend != null) {
playlistElement.setPrivacy(idPrivacy);
}
new Thread(() -> {
try {
String playlistId = new PeertubeAPI(AllPlaylistsActivity.this).createPlaylist(playlistElement);
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
Playlist playlist = new Playlist();
playlist.setId(playlistId);
playlist.setDescription(playlistElement.getDescription());
playlist.setDisplayName(playlistElement.getDisplayName());
playlist.setPrivacy(privacyToSend);
playlists.add(playlist);
playlistAdapter.notifyDataSetChanged();
};
mainHandler.post(myRunnable);
} catch (HttpsConnection.HttpsConnectionException e) {
e.printStackTrace();
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
if (e.getMessage() != null) {
Toasty.error(AllPlaylistsActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
} else {
Toasty.error(AllPlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
};
mainHandler.post(myRunnable);
}
}).start();
dialog.dismiss();
}
} else {
Toasty.error(AllPlaylistsActivity.this, getString(R.string.error_display_name), Toast.LENGTH_LONG).show();
}
});
dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.setTitle(getString(R.string.action_playlist_create));
alertDialog.setOnDismissListener(dialogInterface -> {
//Hide keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
assert imm != null;
imm.hideSoftInputFromWindow(display_name.getWindowToken(), 0);
});
if (alertDialog.getWindow() != null)
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
alertDialog.show();
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (asyncTask != null && !asyncTask.isCancelled()) {
asyncTask.cancel(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActionDone(ManagePlaylistsAsyncTask.action actionType, APIResponse apiResponse, int statusCode) {
mainLoader.setVisibility(View.GONE);
if (apiResponse.getError() != null) {
Toasty.error(AllPlaylistsActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
return;
}
if (actionType == ManagePlaylistsAsyncTask.action.GET_PLAYLIST) {
if (apiResponse.getPlaylists() != null && apiResponse.getPlaylists().size() > 0) {
playlists.addAll(apiResponse.getPlaylists());
playlistAdapter.notifyDataSetChanged();
textviewNoAction.setVisibility(View.GONE);
} else {
textviewNoAction.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onRetrievePeertube(APIResponse apiResponse) {
}
@Override
public void onRetrievePeertubeComments(APIResponse apiResponse) {
}
@Override
public void onRetrievePeertubeChannels(APIResponse apiResponse) {
if (apiResponse.getError() != null || apiResponse.getAccounts() == null || apiResponse.getAccounts().size() == 0) {
if (apiResponse.getError() != null && apiResponse.getError().getError() != null)
Toasty.error(AllPlaylistsActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
else
Toasty.error(AllPlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
return;
}
//Populate channels
List<Account> accounts = apiResponse.getAccounts();
String[] channelName = new String[accounts.size() + 1];
String[] channelId = new String[accounts.size() + 1];
int i = 1;
channelName[0] = "";
channelId[0] = "null";
for (Account account : accounts) {
channelName[i] = account.getUsername();
channelId[i] = account.getId();
i++;
}
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(AllPlaylistsActivity.this,
android.R.layout.simple_spinner_dropdown_item, channelName);
set_upload_channel.setAdapter(adapterChannel);
LinkedHashMap<String, String> translations = null;
if (peertubeInformation.getTranslations() != null)
translations = new LinkedHashMap<>(peertubeInformation.getTranslations());
LinkedHashMap<Integer, String> privaciesInit = new LinkedHashMap<>(peertubeInformation.getPlaylistPrivacies());
Map.Entry<Integer, String> entryInt = privaciesInit.entrySet().iterator().next();
privacyToSend = new HashMap<>();
privacyToSend.put(entryInt.getKey(), entryInt.getValue());
LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPlaylistPrivacies());
//Populate privacies
String[] privaciesA = new String[privacies.size()];
Iterator<Map.Entry<Integer, String>> it = privacies.entrySet().iterator();
i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
privaciesA[i] = pair.getValue();
else
privaciesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(AllPlaylistsActivity.this,
android.R.layout.simple_spinner_dropdown_item, privaciesA);
set_upload_privacy.setAdapter(adapterPrivacies);
//Manage privacies
set_upload_privacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Iterator<Map.Entry<Integer, String>> it = privaciesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position) {
privacyToSend = new HashMap<>();
privacyToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//Manage languages
set_upload_channel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
idChannel = channelId[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}

View File

@@ -0,0 +1,77 @@
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.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;
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.ThemeHelper;
import app.fedilab.fedilabtube.services.GlobalUploadObserver;
import app.fedilab.fedilabtube.worker.WorkHelper;
public class BaseFedilabTube extends MultiDexApplication {
public 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);
if (interval >= 15) {
WorkHelper.fetchNotifications(this, interval);
}
createNotificationChannel();
UploadServiceConfig.initialize(BaseFedilabTube.this, UPLOAD_CHANNEL_ID, true);
new GlobalRequestObserver(this, new GlobalUploadObserver());
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(BaseFedilabTube.this);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int themePref = sharedpreferences.getInt(Helper.SET_THEME, BuildConfig.default_theme);
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

@@ -1,312 +0,0 @@
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.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.google.android.material.textfield.TextInputLayout;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import app.fedilab.fedilabtube.asynctasks.UpdateAccountInfoAsyncTask;
import app.fedilab.fedilabtube.client.HttpsConnection;
import app.fedilab.fedilabtube.helper.Helper;
import es.dmoral.toasty.Toasty;
public class LoginActivity extends AppCompatActivity {
//Peertube notification type
public static int NEW_VIDEO_FROM_SUBSCRIPTION = 1;
// public static int NEW_COMMENT_ON_MY_VIDEO = 2;
// public static int NEW_VIDEO_ABUSE_FOR_MODERATORS = 3;
public static int BLACKLIST_ON_MY_VIDEO = 4;
public static int UNBLACKLIST_ON_MY_VIDEO = 5;
public static int MY_VIDEO_PUBLISHED = 6;
public static int MY_VIDEO_IMPORT_SUCCESS = 7;
public static int MY_VIDEO_IMPORT_ERROR = 8;
private static String client_id;
private static String client_secret;
private EditText login_uid;
private EditText login_passwd;
private Button connectionButton;
private String actionToken;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (getSupportActionBar() != null)
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));
content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0);
content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, R.color.colorAccent)), 0, content_create.length(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
create_an_account_peertube.setText(content_create);
create_an_account_peertube.setOnClickListener(v -> {
Intent mainActivity = new Intent(LoginActivity.this, PeertubeRegisterActivity.class);
Bundle b = new Bundle();
mainActivity.putExtras(b);
startActivity(mainActivity);
});
login_uid = findViewById(R.id.login_uid);
login_passwd = findViewById(R.id.login_passwd);
if (Helper.isTablet(LoginActivity.this)) {
TextInputLayout login_uid_container = findViewById(R.id.login_uid_container);
ViewGroup.LayoutParams layoutParamsU = login_uid_container.getLayoutParams();
layoutParamsU.width = (int) Helper.convertDpToPixel(300, LoginActivity.this);
login_uid_container.setLayoutParams(layoutParamsU);
TextInputLayout login_passwd_container = findViewById(R.id.login_passwd_container);
ViewGroup.LayoutParams layoutParamsP = login_passwd_container.getLayoutParams();
layoutParamsP.width = (int) Helper.convertDpToPixel(300, LoginActivity.this);
login_passwd_container.setLayoutParams(layoutParamsP);
}
connectionButton = findViewById(R.id.login_button);
login_uid.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
if (android.util.Patterns.EMAIL_ADDRESS.matcher(login_uid.getText().toString().trim()).matches()) {
String[] emailArray = login_uid.getText().toString().split("@");
if (emailArray.length > 1 && Arrays.asList(Helper.openid).contains(emailArray[1])) {
connectionButton.callOnClick();
}
}
}
});
connectionButton.setOnClickListener(v -> {
if (!android.util.Patterns.EMAIL_ADDRESS.matcher(login_uid.getText().toString().trim()).matches()) {
Toasty.error(LoginActivity.this, getString(R.string.email_error)).show();
return;
}
String[] emailArray = login_uid.getText().toString().split("@");
if (emailArray.length > 1 && !Arrays.asList(Helper.valideEmails).contains(emailArray[1])) {
Toasty.error(LoginActivity.this, getString(R.string.email_error_domain, emailArray[1])).show();
return;
}
String host = emailArray[1];
String instance = Helper.getPeertubeUrl(host);
final HashMap<String, String> parameters = new HashMap<>();
connectionButton.setEnabled(false);
try {
instance = URLEncoder.encode(instance, "utf-8");
} catch (UnsupportedEncodingException e) {
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
}
if (Arrays.asList(Helper.openid).contains(host)) {
String finalInstance = instance;
new Thread(() -> {
try {
actionToken = "/api/v1/oauth-clients/local";
String response = new HttpsConnection(LoginActivity.this).get("https://" + finalInstance + actionToken, 30, null, null);
if (response == null) {
runOnUiThread(() -> {
connectionButton.setEnabled(true);
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
});
return;
}
JSONObject resobj;
resobj = new JSONObject(response);
client_id = resobj.get(Helper.CLIENT_ID).toString();
client_secret = resobj.get(Helper.CLIENT_SECRET).toString();
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.CLIENT_ID, client_id);
editor.putString(Helper.CLIENT_SECRET, client_secret);
editor.apply();
parameters.clear();
parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null));
parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null));
Intent intent = new Intent(LoginActivity.this, WebviewConnectActivity.class);
Bundle b = new Bundle();
b.putString("url", "https://" + Helper.getPeertubeUrl(host) + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect");
intent.putExtras(b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(() -> {
connectionButton.setEnabled(true);
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
});
}
}).start();
} else {
parameters.clear();
parameters.put(Helper.CLIENT_NAME, Helper.CLIENT_NAME_VALUE);
parameters.put(Helper.REDIRECT_URIS, Helper.REDIRECT_CONTENT);
parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES_PEERTUBE);
parameters.put(Helper.WEBSITE, Helper.WEBSITE_VALUE);
String finalInstance = instance;
new Thread(() -> {
try {
actionToken = "/api/v1/oauth-clients/local";
String response = new HttpsConnection(LoginActivity.this).get("https://" + finalInstance + actionToken, 30, parameters, null);
if (response == null) {
runOnUiThread(() -> {
connectionButton.setEnabled(true);
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
});
return;
}
JSONObject resobj;
try {
resobj = new JSONObject(response);
client_id = resobj.get(Helper.CLIENT_ID).toString();
client_secret = resobj.get(Helper.CLIENT_SECRET).toString();
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.CLIENT_ID, client_id);
editor.putString(Helper.CLIENT_SECRET, client_secret);
editor.apply();
parameters.clear();
parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null));
parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null));
parameters.put("grant_type", "password");
try {
parameters.put("username", URLEncoder.encode(login_uid.getText().toString().trim(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
parameters.put("username", login_uid.getText().toString().trim());
}
try {
parameters.put("password", URLEncoder.encode(login_passwd.getText().toString(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
parameters.put("password", login_passwd.getText().toString());
}
parameters.put("scope", "user");
String oauthUrl = "/api/v1/users/token";
try {
String responseLogin = new HttpsConnection(LoginActivity.this).post("https://" + finalInstance + oauthUrl, 30, parameters, null);
runOnUiThread(() -> {
JSONObject resobjLogin;
try {
resobjLogin = new JSONObject(responseLogin);
String token = resobjLogin.getString("access_token");
String refresh_token = resobjLogin.getString("refresh_token");
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token);
editor.putString(Helper.PREF_INSTANCE, host);
editor.apply();
//Update the account with the token;
new UpdateAccountInfoAsyncTask(LoginActivity.this, token, client_id, client_secret, refresh_token, host).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} catch (JSONException e) {
e.printStackTrace();
runOnUiThread(() -> connectionButton.setEnabled(true));
}
});
} catch (final Exception e) {
e.printStackTrace();
runOnUiThread(() -> {
connectionButton.setEnabled(true);
String message;
if (e.getLocalizedMessage() != null && e.getLocalizedMessage().trim().length() > 0)
message = e.getLocalizedMessage();
else if (e.getMessage() != null && e.getMessage().trim().length() > 0)
message = e.getMessage();
else
message = getString(R.string.client_error);
Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show();
});
}
} catch (JSONException e) {
e.printStackTrace();
e.printStackTrace();
runOnUiThread(() -> connectionButton.setEnabled(true));
}
} catch (final Exception e) {
e.printStackTrace();
runOnUiThread(() -> {
connectionButton.setEnabled(true);
String message = null;
if (e.getLocalizedMessage() != null) {
message = e.getMessage();
}
if (message == null) {
message = getString(R.string.client_error);
}
Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show();
});
}
}).start();
}
});
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}

View File

@@ -1,248 +0,0 @@
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.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.navigation.NavController;
import androidx.navigation.NavGraph;
import androidx.navigation.NavInflater;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
import app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyncTask;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import static app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyncTask.peertubeInformation;
import static app.fedilab.fedilabtube.helper.Helper.academies;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
if (Helper.isLoggedIn(MainActivity.this)) {
navView.inflateMenu(R.menu.bottom_nav_menu_connected);
} else {
navView.inflateMenu(R.menu.bottom_nav_menu);
}
try {
peertubeInformation = new PeertubeInformation();
peertubeInformation.setCategories(new LinkedHashMap<>());
peertubeInformation.setLanguages(new LinkedHashMap<>());
peertubeInformation.setLicences(new LinkedHashMap<>());
peertubeInformation.setPrivacies(new LinkedHashMap<>());
peertubeInformation.setPlaylistPrivacies(new LinkedHashMap<>());
peertubeInformation.setTranslations(new LinkedHashMap<>());
new RetrievePeertubeInformationAsyncTask(MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} catch (Exception ignored) {
}
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration;
//Bottom menu won't be the same if the user is authenticated
//When the user is authenticated, the subscription entry will be added and the local one removed.
if (Helper.isLoggedIn(MainActivity.this)) {
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_discover, R.id.navigation_subscription, R.id.navigation_trending, R.id.navigation_most_liked, R.id.navigation_recently_added)
.build();
} else {
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_discover, R.id.navigation_trending, R.id.navigation_most_liked, R.id.navigation_recently_added, R.id.navigation_home)
.build();
}
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
if (navHostFragment != null) {
NavInflater inflater = navHostFragment.getNavController().getNavInflater();
NavGraph graph;
//the menu is inflated for authenticated or not authenticated account
if (Helper.isLoggedIn(MainActivity.this)) {
graph = inflater.inflate(R.navigation.mobile_navigation_connected);
} else {
graph = inflater.inflate(R.navigation.mobile_navigation);
}
navHostFragment.getNavController().setGraph(graph);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
}
}
@Override
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) myActionMenuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
Intent intent = new Intent(MainActivity.this, SearchActivity.class);
Bundle b = new Bundle();
String search = query.trim();
b.putString("search", search);
intent.putExtras(b);
startActivity(intent);
if (!searchView.isIconified()) {
searchView.setIconified(true);
}
myActionMenuItem.collapseActionView();
return false;
}
@Override
public boolean onQueryTextChange(String s) {
return false;
}
});
MenuItem instanceItem = menu.findItem(R.id.action_change_instance);
MenuItem uploadItem = menu.findItem(R.id.action_upload);
MenuItem myVideosItem = menu.findItem(R.id.action_myvideos);
MenuItem playslistItem = menu.findItem(R.id.action_playlist);
MenuItem historyItem = menu.findItem(R.id.action_history);
if (Helper.isLoggedIn(MainActivity.this)) {
instanceItem.setVisible(false);
uploadItem.setVisible(true);
myVideosItem.setVisible(true);
playslistItem.setVisible(true);
historyItem.setVisible(true);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, 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).getUniqAccount(userId, instance);
if (account != null) {
new Thread(() -> new PeertubeAPI(MainActivity.this).refreshToken(account.getToken(), account.getInstance())).start();
}
} else {
instanceItem.setVisible(true);
uploadItem.setVisible(false);
myVideosItem.setVisible(false);
playslistItem.setVisible(false);
historyItem.setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_change_instance) {
showRadioButtonDialog();
return true;
} else if (item.getItemId() == R.id.action_account) {
Intent intent;
if (Helper.isLoggedIn(MainActivity.this)) {
intent = new Intent(MainActivity.this, AccountActivity.class);
} else {
intent = new Intent(MainActivity.this, LoginActivity.class);
}
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.action_upload) {
Intent intent = new Intent(MainActivity.this, PeertubeUploadActivity.class);
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.action_myvideos) {
Intent intent = new Intent(MainActivity.this, MyVideosActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.MYVIDEOS);
intent.putExtras(bundle);
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.action_history) {
Intent intent = new Intent(MainActivity.this, MyVideosActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PEERTUBE_HISTORY);
intent.putExtras(bundle);
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.action_playlist) {
Intent intent = new Intent(MainActivity.this, AllPlaylistsActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent == null)
return;
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(Helper.INTENT_ACTION)) {
if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) {
recreate();
}
}
}
@SuppressLint("ApplySharedPref")
private void showRadioButtonDialog() {
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(R.string.instance_choice);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String acad = Helper.getLiveInstance(MainActivity.this);
int i = 0;
for (String item : academies) {
if (item.compareTo(acad) == 0) {
break;
}
i++;
}
alt_bld.setSingleChoiceItems(academies, i, (dialog, item) -> {
String newInstance = academies[item];
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_INSTANCE, newInstance);
editor.commit();
dialog.dismiss();
recreate();
});
AlertDialog alert = alt_bld.create();
alert.show();
}
}

View File

@@ -1,79 +0,0 @@
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 androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.fragment.DisplayStatusFragment;
import app.fedilab.fedilabtube.interfaces.OnRetrieveFeedsInterface;
public class MyVideosActivity extends AppCompatActivity implements OnRetrieveFeedsInterface {
private RetrieveFeedsAsyncTask.Type type;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Bundle b = getIntent().getExtras();
if (b != null)
type = (RetrieveFeedsAsyncTask.Type) b.get("type");
if (type == RetrieveFeedsAsyncTask.Type.MYVIDEOS) {
setTitle(R.string.my_videos);
} else if (type == RetrieveFeedsAsyncTask.Type.PSUBSCRIPTIONS) {
setTitle(R.string.subscriptions);
} else if (type == RetrieveFeedsAsyncTask.Type.PEERTUBE_HISTORY) {
setTitle(R.string.my_history);
}
if (savedInstanceState == null) {
DisplayStatusFragment displayStatusFragment = new DisplayStatusFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("type", type);
displayStatusFragment.setArguments(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, displayStatusFragment).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRetrieveFeeds(APIResponse apiResponse) {
}
}

View File

@@ -1,844 +0,0 @@
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.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import org.jetbrains.annotations.NotNull;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.HttpsURLConnection;
import app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.PostActionAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeSingleAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeSingleCommentsAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.TLSSocketFactory;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.Peertube;
import app.fedilab.fedilabtube.client.entities.Playlist;
import app.fedilab.fedilabtube.client.entities.PlaylistElement;
import app.fedilab.fedilabtube.client.entities.Status;
import app.fedilab.fedilabtube.client.entities.StatusDrawerParams;
import app.fedilab.fedilabtube.drawer.StatusListAdapter;
import app.fedilab.fedilabtube.helper.CacheDataSourceFactory;
import app.fedilab.fedilabtube.helper.FullScreenMediaController;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnPlaylistActionInterface;
import app.fedilab.fedilabtube.interfaces.OnPostActionInterface;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.PeertubeFavoritesDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.webview.CustomWebview;
import app.fedilab.fedilabtube.webview.MastalabWebChromeClient;
import app.fedilab.fedilabtube.webview.MastalabWebViewClient;
import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask.action.GET_PLAYLIST;
import static app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask.action.GET_PLAYLIST_FOR_VIDEO;
import static app.fedilab.fedilabtube.helper.Helper.getAttColor;
import static app.fedilab.fedilabtube.helper.Helper.isLoggedIn;
public class PeertubeActivity extends AppCompatActivity implements OnRetrievePeertubeInterface, OnPostActionInterface, OnPlaylistActionInterface {
public static String video_id;
private String peertubeInstance, videoId;
private FullScreenMediaController.fullscreen fullscreen;
private RelativeLayout loader;
private TextView peertube_view_count, peertube_playlist, peertube_bookmark, peertube_like_count, peertube_dislike_count, peertube_share, peertube_download, peertube_description, peertube_title;
private ScrollView peertube_information_container;
private Peertube peertube;
private PlayerView playerView;
private SimpleExoPlayer player;
private boolean fullScreenMode;
private Dialog fullScreenDialog;
private AppCompatImageView fullScreenIcon;
private TextView resolution;
private int mode;
private LinearLayout write_comment_container;
private ImageView send;
private TextView add_comment_read;
private EditText add_comment_write;
private List<PlaylistElement> playlistForVideo;
private List<Playlist> playlists;
public static void hideKeyboard(Activity activity) {
if (activity != null && activity.getWindow() != null) {
activity.getWindow().getDecorView();
InputMethodManager imm = (InputMethodManager) activity.getSystemService(INPUT_METHOD_SERVICE);
assert imm != null;
imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
fullscreen = FullScreenMediaController.fullscreen.OFF;
fullScreenMode = false;
playlistForVideo = new ArrayList<>();
setContentView(R.layout.activity_peertube);
loader = findViewById(R.id.loader);
peertube_view_count = findViewById(R.id.peertube_view_count);
peertube_bookmark = findViewById(R.id.peertube_bookmark);
peertube_like_count = findViewById(R.id.peertube_like_count);
peertube_dislike_count = findViewById(R.id.peertube_dislike_count);
peertube_share = findViewById(R.id.peertube_share);
peertube_download = findViewById(R.id.peertube_download);
peertube_description = findViewById(R.id.peertube_description);
peertube_title = findViewById(R.id.peertube_title);
peertube_information_container = findViewById(R.id.peertube_information_container);
CustomWebview webview_video = findViewById(R.id.webview_video);
playerView = findViewById(R.id.media_video);
write_comment_container = findViewById(R.id.write_comment_container);
ImageView my_pp = findViewById(R.id.my_pp);
add_comment_read = findViewById(R.id.add_comment_read);
add_comment_write = findViewById(R.id.add_comment_write);
peertube_playlist = findViewById(R.id.peertube_playlist);
send = findViewById(R.id.send);
peertube_playlist.setVisibility(View.VISIBLE);
peertube_bookmark.setVisibility(View.GONE);
if (Helper.isTablet(PeertubeActivity.this)) {
RelativeLayout video_container = findViewById(R.id.video_container);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
0,
2.0f
);
video_container.setLayoutParams(param);
}
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(PeertubeActivity.this);
Account account = new AccountDAO(PeertubeActivity.this, db).getUniqAccount(userId, instance);
Helper.loadGiF(PeertubeActivity.this, account, my_pp);
Bundle b = getIntent().getExtras();
if (b != null) {
peertubeInstance = b.getString("peertube_instance", Helper.getLiveInstance(PeertubeActivity.this));
videoId = b.getString("video_id", null);
}
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
if (mode != Helper.VIDEO_MODE_WEBVIEW && mode != Helper.VIDEO_MODE_NORMAL)
mode = Helper.VIDEO_MODE_NORMAL;
if (mode == Helper.VIDEO_MODE_WEBVIEW) {
webview_video.setVisibility(View.VISIBLE);
playerView.setVisibility(View.GONE);
webview_video = Helper.initializeWebview(PeertubeActivity.this, R.id.webview_video, null);
FrameLayout webview_container = findViewById(R.id.main_media_frame);
final ViewGroup videoLayout = findViewById(R.id.videoLayout);
MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient(PeertubeActivity.this, webview_video, webview_container, videoLayout);
mastalabWebChromeClient.setOnToggledFullscreen(fullscreen -> {
if (fullscreen) {
videoLayout.setVisibility(View.VISIBLE);
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
getWindow().setAttributes(attrs);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
peertube_information_container.setVisibility(View.GONE);
} else {
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
getWindow().setAttributes(attrs);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
videoLayout.setVisibility(View.GONE);
peertube_information_container.setVisibility(View.VISIBLE);
}
});
webview_video.getSettings().setAllowFileAccess(true);
webview_video.setWebChromeClient(mastalabWebChromeClient);
webview_video.getSettings().setDomStorageEnabled(true);
webview_video.getSettings().setAppCacheEnabled(true);
webview_video.getSettings().setMediaPlaybackRequiresUserGesture(false);
webview_video.setWebViewClient(new MastalabWebViewClient(PeertubeActivity.this));
webview_video.loadUrl("https://" + peertubeInstance + "/videos/embed/" + videoId);
} else {
webview_video.setVisibility(View.GONE);
playerView.setVisibility(View.VISIBLE);
loader.setVisibility(View.VISIBLE);
}
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
playerView.setControllerShowTimeoutMs(1000);
playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
initFullscreenDialog();
initFullscreenButton();
}
if (Helper.isLoggedIn(PeertubeActivity.this)) {
new ManagePlaylistsAsyncTask(PeertubeActivity.this, GET_PLAYLIST, null, null, null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
new RetrievePeertubeSingleAsyncTask(PeertubeActivity.this, peertubeInstance, videoId, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void change() {
if (fullscreen == FullScreenMediaController.fullscreen.ON) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Objects.requireNonNull(getSupportActionBar()).hide();
peertube_information_container.setVisibility(View.GONE);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
Objects.requireNonNull(getSupportActionBar()).show();
peertube_information_container.setVisibility(View.VISIBLE);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
View v = getCurrentFocus();
if ((ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) &&
v instanceof EditText &&
v.getId() == R.id.add_comment_write) {
int[] scrcoords = new int[2];
v.getLocationOnScreen(scrcoords);
float x = ev.getRawX() + v.getLeft() - scrcoords[0];
float y = ev.getRawY() + v.getTop() - scrcoords[1];
if (x < v.getLeft() || x > v.getRight() || y < v.getTop() || y > v.getBottom()) {
add_comment_read.setVisibility(View.VISIBLE);
add_comment_write.setVisibility(View.GONE);
send.setVisibility(View.GONE);
hideKeyboard(PeertubeActivity.this);
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
getMenuInflater().inflate(R.menu.main_peertube, 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_report) {
androidx.appcompat.app.AlertDialog.Builder dialogBuilder = new androidx.appcompat.app.AlertDialog.Builder(PeertubeActivity.this);
LayoutInflater inflater1 = getLayoutInflater();
View dialogView = inflater1.inflate(R.layout.popup_report_choice, new LinearLayout(PeertubeActivity.this), false);
dialogBuilder.setView(dialogView);
Button report_video = dialogView.findViewById(R.id.report_video);
Button report_account = dialogView.findViewById(R.id.report_account);
dialogBuilder.setNeutralButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
androidx.appcompat.app.AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
report_video.setOnClickListener(v -> reportAlert(PeertubeAPI.reportType.VIDEO, alertDialog));
report_account.setOnClickListener(v -> reportAlert(PeertubeAPI.reportType.ACCOUNT, alertDialog));
return true;
}
return super.onOptionsItemSelected(item);
}
private void reportAlert(PeertubeAPI.reportType type, androidx.appcompat.app.AlertDialog alertDialog) {
androidx.appcompat.app.AlertDialog.Builder dialogBuilder = new androidx.appcompat.app.AlertDialog.Builder(PeertubeActivity.this);
LayoutInflater inflater1 = getLayoutInflater();
View dialogView = inflater1.inflate(R.layout.popup_report, new LinearLayout(PeertubeActivity.this), false);
dialogBuilder.setView(dialogView);
EditText report_content = dialogView.findViewById(R.id.report_content);
dialogBuilder.setNeutralButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
dialogBuilder.setPositiveButton(R.string.report, (dialog, id) -> {
if (report_content.getText().toString().trim().length() == 0) {
Toasty.info(PeertubeActivity.this, getString(R.string.report_comment_size), Toasty.LENGTH_LONG).show();
} else {
if (type == PeertubeAPI.reportType.VIDEO) {
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.REPORT_VIDEO, peertube.getId(), report_content.getText().toString(), PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
alertDialog.dismiss();
dialog.dismiss();
} else if (type == PeertubeAPI.reportType.ACCOUNT) {
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.REPORT_ACCOUNT, peertube.getAccount().getId(), report_content.getText().toString(), PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
alertDialog.dismiss();
dialog.dismiss();
}
}
});
androidx.appcompat.app.AlertDialog alertDialog2 = dialogBuilder.create();
alertDialog2.show();
}
public FullScreenMediaController.fullscreen getFullscreen() {
return fullscreen;
}
public void setFullscreen(FullScreenMediaController.fullscreen fullscreen) {
this.fullscreen = fullscreen;
}
@Override
public void onRetrievePeertube(APIResponse apiResponse) {
if (apiResponse == null || (apiResponse.getError() != null) || apiResponse.getPeertubes() == null || apiResponse.getPeertubes().size() == 0) {
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
loader.setVisibility(View.GONE);
return;
}
if (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().get(0) == null || apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this) == null) {
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
loader.setVisibility(View.GONE);
return;
}
peertube = apiResponse.getPeertubes().get(0);
//TODO: currently streaming service gives the wrong values for duration
new ManagePlaylistsAsyncTask(PeertubeActivity.this, GET_PLAYLIST_FOR_VIDEO, null, peertube.getId(), null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
add_comment_read.setOnClickListener(v -> {
if (isLoggedIn(PeertubeActivity.this)) {
add_comment_read.setVisibility(View.GONE);
add_comment_write.setVisibility(View.VISIBLE);
send.setVisibility(View.VISIBLE);
add_comment_write.requestFocus();
add_comment_write.setSelection(add_comment_write.getText().length());
} else {
Toasty.error(PeertubeActivity.this, getString(R.string.not_logged_in), Toast.LENGTH_SHORT).show();
}
});
send.setOnClickListener(v -> {
if (isLoggedIn(PeertubeActivity.this)) {
String comment = add_comment_write.getText().toString();
if (comment.trim().length() > 0) {
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.PEERTUBECOMMENT, peertube.getId(), comment, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
add_comment_write.setText("");
add_comment_read.setVisibility(View.VISIBLE);
add_comment_write.setVisibility(View.GONE);
send.setVisibility(View.GONE);
add_comment_read.requestFocus();
}
} else {
Toasty.error(PeertubeActivity.this, getString(R.string.not_logged_in), Toast.LENGTH_SHORT).show();
}
});
peertube_playlist.setOnClickListener(v -> {
if (playlists != null && peertube.getId() != null) {
PopupMenu popup = new PopupMenu(PeertubeActivity.this, peertube_playlist);
for (Playlist playlist : playlists) {
String title = null;
boolean isPresent = false;
String elementId = null;
PlaylistElement playlistElementFinal = null;
for (PlaylistElement playlistElement : playlistForVideo) {
if (playlist.getId().equals(playlistElement.getPlaylistId())) {
title = "" + playlist.getDisplayName();
isPresent = true;
elementId = playlistElement.getPlaylistElementId();
playlistElementFinal = playlistElement;
break;
}
}
if (title == null) {
title = playlist.getDisplayName();
}
MenuItem item = popup.getMenu().add(0, 0, Menu.NONE, title);
boolean finalIsPresent = isPresent;
String finalElementId = elementId;
PlaylistElement finalPlaylistElementFinal = playlistElementFinal;
item.setOnMenuItemClickListener(item1 -> {
item1.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item1.setActionView(new View(PeertubeActivity.this));
item1.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item1) {
return false;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item1) {
return false;
}
});
if (finalIsPresent) {
item1.setTitle(playlist.getDisplayName());
new ManagePlaylistsAsyncTask(PeertubeActivity.this, ManagePlaylistsAsyncTask.action.DELETE_VIDEOS, playlist, finalElementId, null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
playlistForVideo.remove(finalPlaylistElementFinal);
} else {
item1.setTitle("" + playlist.getDisplayName());
new ManagePlaylistsAsyncTask(PeertubeActivity.this, ManagePlaylistsAsyncTask.action.ADD_VIDEOS, playlist, peertube.getId(), null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
PlaylistElement playlistElement = new PlaylistElement();
playlistElement.setPlaylistElementId(finalElementId);
playlistElement.setPlaylistId(playlist.getId());
playlistForVideo.add(playlistElement);
}
return false;
});
popup.show();
}
}
});
if (peertube.isCommentsEnabled()) {
new RetrievePeertubeSingleCommentsAsyncTask(PeertubeActivity.this, peertubeInstance, videoId, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
write_comment_container.setVisibility(View.VISIBLE);
} else {
RelativeLayout no_action = findViewById(R.id.no_action);
TextView no_action_text = findViewById(R.id.no_action_text);
no_action_text.setText(getString(R.string.comment_no_allowed_peertube));
no_action.setVisibility(View.VISIBLE);
write_comment_container.setVisibility(View.GONE);
}
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
setTitle(peertube.getName());
peertube_description.setText(peertube.getDescription());
peertube_title.setText(peertube.getName());
peertube_dislike_count.setText(String.valueOf(peertube.getDislike()));
peertube_like_count.setText(String.valueOf(peertube.getLike()));
peertube_view_count.setText(String.valueOf(peertube.getView()));
video_id = peertube.getId();
changeColor();
initResolution();
peertube_like_count.setOnClickListener(v -> {
if (isLoggedIn(PeertubeActivity.this)) {
String newState = peertube.getMyRating().equals("like") ? "none" : "like";
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.RATEVIDEO, peertube.getId(), newState, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
peertube.setMyRating(newState);
int count = Integer.parseInt(peertube_like_count.getText().toString());
if (newState.compareTo("none") == 0) {
count--;
if (count - 1 < 0) {
count = 0;
}
} else {
count++;
}
peertube_like_count.setText(String.valueOf(count));
changeColor();
} else {
Toasty.error(PeertubeActivity.this, getString(R.string.not_logged_in), Toast.LENGTH_SHORT).show();
}
});
peertube_dislike_count.setOnClickListener(v -> {
if (isLoggedIn(PeertubeActivity.this)) {
String newState = peertube.getMyRating().equals("dislike") ? "none" : "dislike";
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.RATEVIDEO, peertube.getId(), newState, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
peertube.setMyRating(newState);
int count = Integer.parseInt(peertube_dislike_count.getText().toString());
if (newState.compareTo("none") == 0) {
count--;
if (count - 1 < 0) {
count = 0;
}
} else {
count++;
}
peertube_dislike_count.setText(String.valueOf(count));
changeColor();
} else {
Toasty.error(PeertubeActivity.this, getString(R.string.not_logged_in), Toast.LENGTH_SHORT).show();
}
});
try {
HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory());
} catch (KeyManagementException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (mode == Helper.VIDEO_MODE_NORMAL) {
int video_cache = sharedpreferences.getInt(Helper.SET_VIDEO_CACHE, Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
if (video_cache == 0) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this,
Util.getUserAgent(PeertubeActivity.this, null), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this)));
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this);
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this)));
}
player = ExoPlayerFactory.newSimpleInstance(PeertubeActivity.this);
playerView.setPlayer(player);
loader.setVisibility(View.GONE);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
peertube_download.setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(PeertubeActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(PeertubeActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PeertubeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
} else {
Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, PeertubeActivity.this));
}
} else {
Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, PeertubeActivity.this));
}
});
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<Peertube> peertubes = new PeertubeFavoritesDAO(PeertubeActivity.this, db).getSinglePeertube(peertube);
Drawable img;
if (peertubes == null || peertubes.size() == 0)
img = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_bookmark_border_24);
else
img = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_bookmark_24);
peertube_bookmark.setCompoundDrawablesWithIntrinsicBounds(null, img, null, null);
peertube_bookmark.setOnClickListener(v -> {
List<Peertube> peertubes1 = new PeertubeFavoritesDAO(PeertubeActivity.this, db).getSinglePeertube(peertube);
if (peertubes1 == null || peertubes1.size() == 0) {
new PeertubeFavoritesDAO(PeertubeActivity.this, db).insert(peertube);
Toasty.success(PeertubeActivity.this, getString(R.string.bookmark_add_peertube), Toast.LENGTH_SHORT).show();
} else {
new PeertubeFavoritesDAO(PeertubeActivity.this, db).remove(peertube);
Toasty.success(PeertubeActivity.this, getString(R.string.bookmark_remove_peertube), Toast.LENGTH_SHORT).show();
}
if (peertubes1 != null && peertubes1.size() > 0) //Was initially in cache
peertube_bookmark.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_bookmark_border_24), null, null);
else
peertube_bookmark.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_bookmark_24), null, null);
});
peertube_share.setOnClickListener(v -> {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.shared_via));
String url;
url = "https://" + peertube.getInstance() + "/videos/watch/" + peertube.getUuid();
boolean share_details = sharedpreferences.getBoolean(Helper.SET_SHARE_DETAILS, true);
String extra_text;
if (share_details) {
extra_text = "@" + peertube.getAccount().getAcct();
extra_text += "\r\n\r\n" + peertube.getName();
extra_text += "\n\n\uD83D\uDD17 " + url + "\r\n-\n";
final String contentToot;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
contentToot = Html.fromHtml(peertube.getDescription(), Html.FROM_HTML_MODE_LEGACY).toString();
else
contentToot = Html.fromHtml(peertube.getDescription()).toString();
extra_text += contentToot;
} else {
extra_text = url;
}
sendIntent.putExtra(Intent.EXTRA_TEXT, extra_text);
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getString(R.string.share_with)));
});
}
@Override
public void onConfigurationChanged(@NotNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
openFullscreenDialog();
}
setFullscreen(FullScreenMediaController.fullscreen.ON);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
closeFullscreenDialog();
}
setFullscreen(FullScreenMediaController.fullscreen.OFF);
}
change();
}
@Override
public void onRetrievePeertubeComments(APIResponse apiResponse) {
if (apiResponse == null || (apiResponse.getError() != null && apiResponse.getError().getStatusCode() != 404 && apiResponse.getError() != null && apiResponse.getError().getStatusCode() != 501)) {
if (apiResponse == null)
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
else
Toasty.error(PeertubeActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
return;
}
List<Status> statuses = apiResponse.getStatuses();
RecyclerView lv_comments = findViewById(R.id.peertube_comments);
if (statuses != null && statuses.size() > 0) {
lv_comments.setVisibility(View.VISIBLE);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
StatusDrawerParams statusDrawerParams = new StatusDrawerParams();
statusDrawerParams.setTargetedId(userId);
statusDrawerParams.setStatuses(statuses);
StatusListAdapter statusListAdapter = new StatusListAdapter(statusDrawerParams);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(PeertubeActivity.this);
lv_comments.setLayoutManager(mLayoutManager);
lv_comments.setNestedScrollingEnabled(false);
lv_comments.setAdapter(statusListAdapter);
}
}
@Override
public void onRetrievePeertubeChannels(APIResponse apiResponse) {
}
@Override
public void onDestroy() {
super.onDestroy();
if (player != null)
player.release();
}
@Override
protected void onPause() {
super.onPause();
if (player != null) {
player.setPlayWhenReady(false);
}
}
@Override
public void onResume() {
super.onResume();
if (player != null) {
player.setPlayWhenReady(true);
}
}
public void displayResolution() {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
AlertDialog.Builder builderSingle = new AlertDialog.Builder(PeertubeActivity.this);
builderSingle.setTitle(R.string.pickup_resolution);
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(PeertubeActivity.this, android.R.layout.select_dialog_item);
for (String resolution : peertube.getResolution())
arrayAdapter.add(resolution + "p");
builderSingle.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderSingle.setAdapter(arrayAdapter, (dialog, which) -> {
String res = Objects.requireNonNull(arrayAdapter.getItem(which)).substring(0, Objects.requireNonNull(arrayAdapter.getItem(which)).length() - 1);
if (playerView != null) {
loader.setVisibility(View.VISIBLE);
long position = player.getCurrentPosition();
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
resolution = controlView.findViewById(R.id.resolution);
resolution.setText(String.format("%sp", res));
if (mode == Helper.VIDEO_MODE_NORMAL) {
if (player != null)
player.release();
player = ExoPlayerFactory.newSimpleInstance(PeertubeActivity.this);
playerView.setPlayer(player);
loader.setVisibility(View.GONE);
int video_cache = sharedpreferences.getInt(Helper.SET_VIDEO_CACHE, Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
if (video_cache == 0) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this,
Util.getUserAgent(PeertubeActivity.this, null), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(peertube.getFileUrl(res, PeertubeActivity.this)));
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this);
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(Uri.parse(peertube.getFileUrl(res, PeertubeActivity.this)));
}
player.prepare(videoSource);
player.seekTo(0, position);
player.setPlayWhenReady(true);
}
}
});
builderSingle.show();
}
@Override
public void onPostAction(int statusCode, PeertubeAPI.StatusAction statusAction, String userId, Error error) {
if (peertube.isCommentsEnabled() && statusAction == PeertubeAPI.StatusAction.PEERTUBECOMMENT) {
new RetrievePeertubeSingleCommentsAsyncTask(PeertubeActivity.this, peertubeInstance, videoId, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else if (statusAction == PeertubeAPI.StatusAction.REPORT_ACCOUNT) {
Toasty.success(PeertubeActivity.this, getString(R.string.successful_report), Toasty.LENGTH_LONG).show();
} else if (statusAction == PeertubeAPI.StatusAction.REPORT_VIDEO) {
Toasty.success(PeertubeActivity.this, getString(R.string.successful_video_report), Toasty.LENGTH_LONG).show();
}
}
private void initFullscreenDialog() {
fullScreenDialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
public void onBackPressed() {
if (fullScreenMode)
closeFullscreenDialog();
super.onBackPressed();
}
};
}
private void openFullscreenDialog() {
((ViewGroup) playerView.getParent()).removeView(playerView);
fullScreenDialog.addContentView(playerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
fullScreenIcon.setImageDrawable(ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_fullscreen_exit_24));
fullScreenMode = true;
fullScreenDialog.show();
}
private void closeFullscreenDialog() {
((ViewGroup) playerView.getParent()).removeView(playerView);
((FrameLayout) findViewById(R.id.main_media_frame)).addView(playerView);
fullScreenMode = false;
fullScreenDialog.dismiss();
fullScreenIcon.setImageDrawable(ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_fullscreen_24));
}
private void initFullscreenButton() {
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
fullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
View fullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
fullScreenButton.setOnClickListener(v -> {
if (!fullScreenMode)
openFullscreenDialog();
else
closeFullscreenDialog();
});
}
private void initResolution() {
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
resolution = controlView.findViewById(R.id.resolution);
resolution.setText(String.format("%sp", peertube.getResolution().get(0)));
resolution.setOnClickListener(v -> displayResolution());
}
private void changeColor() {
Drawable thumbUp = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_thumb_up_alt_24);
Drawable thumbDown = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_baseline_thumb_down_alt_24);
int color = getAttColor(this, android.R.attr.colorControlNormal);
if (thumbUp != null) {
thumbUp.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
DrawableCompat.setTint(thumbUp, color);
}
if (thumbDown != null) {
thumbDown.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
DrawableCompat.setTint(thumbDown, color);
}
if (peertube.getMyRating() != null && peertube.getMyRating().compareTo("like") == 0) {
if (thumbUp != null) {
thumbUp.setColorFilter(getResources().getColor(R.color.positive_thumbs), PorterDuff.Mode.SRC_ATOP);
DrawableCompat.setTint(thumbUp, getResources().getColor(R.color.positive_thumbs));
}
} else if (peertube.getMyRating() != null && peertube.getMyRating().compareTo("dislike") == 0) {
if (thumbDown != null) {
thumbDown.setColorFilter(getResources().getColor(R.color.negative_thumbs), PorterDuff.Mode.SRC_ATOP);
DrawableCompat.setTint(thumbDown, getResources().getColor(R.color.negative_thumbs));
}
}
peertube_like_count.setCompoundDrawablesWithIntrinsicBounds(null, thumbUp, null, null);
peertube_dislike_count.setCompoundDrawablesWithIntrinsicBounds(null, thumbDown, null, null);
}
@Override
public void onActionDone(ManagePlaylistsAsyncTask.action actionType, APIResponse apiResponse, int statusCode) {
if (actionType == GET_PLAYLIST_FOR_VIDEO && apiResponse != null) {
playlistForVideo = apiResponse.getPlaylistForVideos();
} else if (actionType == GET_PLAYLIST && apiResponse != null) {
playlists = apiResponse.getPlaylists();
}
}
}

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