Compare commits
56 Commits
Author | SHA1 | Date | |
---|---|---|---|
74e45b1820 | |||
0a1336f0e0 | |||
d5a0dcb980 | |||
83e7c41ca0 | |||
1d1b0c11a9 | |||
3b2c4e2ac6 | |||
2d77fe580f | |||
7ae20f43f8 | |||
f03c1b206b | |||
d99a58f2cf | |||
5aeaf7f34b | |||
af0b484d16 | |||
0a6791b752 | |||
e73e306d05 | |||
52189abbff | |||
d721f12d74 | |||
69f28bb647 | |||
2b2295d831 | |||
179586b8c4 | |||
1afad9e06a | |||
59c73fd864 | |||
6820344750 | |||
680504791c | |||
41e500a8f8 | |||
448af1ef9a | |||
041e8c0bd6 | |||
0b7300e93a | |||
94c5f5a705 | |||
fa2f8a7b05 | |||
aeb288142e | |||
635c43f458 | |||
d36138431b | |||
9cdf857730 | |||
52a6152af6 | |||
9d3312c081 | |||
1146236f46 | |||
ec19ee1e55 | |||
cc37e40158 | |||
bdd12de34d | |||
e64692d0d3 | |||
7da8c0f664 | |||
fc41c077dc | |||
50800da4b9 | |||
a9219e8a91 | |||
5eedadef47 | |||
14cde8e625 | |||
1f2ecd591d | |||
9a2eb6cd49 | |||
aa38514bcb | |||
f2fddfb16c | |||
05300682c1 | |||
a3714a4ecf | |||
500584b9ef | |||
33ac822957 | |||
d3ffc32d9b | |||
a6dfd842e3 |
@ -68,7 +68,7 @@ assembleDebug:
|
||||
cache:
|
||||
key: "${CI_COMMIT_TAG}"
|
||||
paths:
|
||||
- app/build/outputs/apk/fdroid_acad/debug/app-fdroid_acad-debug.apk
|
||||
- app/build/outputs/apk/fdroid_peertube_apps_educ/debug/app-fdroid_peertube_apps_educ-debug.apk
|
||||
- app/build/outputs/apk/fdroid_full/debug/app-fdroid_full-debug.apk
|
||||
policy: push
|
||||
script:
|
||||
@ -76,11 +76,11 @@ assembleDebug:
|
||||
|
||||
# Basic android and gradle stuff
|
||||
# Check linting
|
||||
lintFdroid_acadDebug:
|
||||
lintfdroid_peertube_apps_educDebug:
|
||||
interruptible: true
|
||||
stage: build
|
||||
script:
|
||||
- ./gradlew -Pci --console=plain :app:lintFdroid_acadDebug -PbuildDir=lint
|
||||
- ./gradlew -Pci --console=plain :app:lintfdroid_peertube_apps_educDebug -PbuildDir=lint
|
||||
except:
|
||||
- tags
|
||||
|
||||
@ -110,7 +110,7 @@ putApkOnTags:
|
||||
cache:
|
||||
key: "${CI_COMMIT_TAG}"
|
||||
paths:
|
||||
- app/build/outputs/apk/fdroid_acad/debug/app-fdroid_acad-debug.apk
|
||||
- app/build/outputs/apk/fdroid_peertube_apps_educ/debug/app-fdroid_peertube_apps_educ-debug.apk
|
||||
- app/build/outputs/apk/fdroid_full/debug/app-fdroid_full-debug.apk
|
||||
policy: pull
|
||||
script:
|
||||
@ -120,11 +120,11 @@ putApkOnTags:
|
||||
- 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 acadUrl="${NC_DOWNLOAD_URL}app-fdroid_peertube_apps_educ-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"'
|
||||
- 'curl -s -u "${NC_USER}:${NC_PASSWORD}" -T app/build/outputs/apk/fdroid_peertube_apps_educ/debug/app-fdroid_peertube_apps_educ-debug.apk "${NC_UPLOAD_URL}/app-fdroid_peertube_apps_educ-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
|
||||
|
@ -9,8 +9,8 @@ android {
|
||||
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 30
|
||||
versionName "1.10.0"
|
||||
versionCode 33
|
||||
versionName "1.10.2"
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@ -38,8 +38,9 @@ android {
|
||||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
}
|
||||
//boolean full_instances if set to false means TubeAcad
|
||||
productFlavors {
|
||||
fdroid_acad {
|
||||
fdroid_peertube_apps_educ {
|
||||
applicationId "app.fedilab.fedilabtube"
|
||||
resValue "string", "app_name", "TubeAcad"
|
||||
resValue "string", "app_id", "app.fedilab.fedilabtube"
|
||||
@ -50,7 +51,7 @@ android {
|
||||
buildConfigField "boolean", "sepia_search", "false"
|
||||
buildConfigField "boolean", "instance_switcher", "true"
|
||||
}
|
||||
google_acad {
|
||||
google_peertube_apps_educ {
|
||||
applicationId "app.fedilab.fedilabtube"
|
||||
resValue "string", "app_name", "TubeAcad"
|
||||
resValue "string", "app_id", "app.fedilab.fedilabtube"
|
||||
@ -109,23 +110,29 @@ android {
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
fdroid_acad {
|
||||
fdroid_peertube_apps_educ {
|
||||
res.srcDirs = ['src/main/res', 'src/acad/res']
|
||||
java.srcDirs = ['src/main/java', 'src/acad/java']
|
||||
}
|
||||
google_acad {
|
||||
google_peertube_apps_educ {
|
||||
res.srcDirs = ['src/main/res', 'src/acad/res']
|
||||
java.srcDirs = ['src/main/java', 'src/acad/java']
|
||||
}
|
||||
fdroid_full {
|
||||
res.srcDirs = ['src/main/res', 'src/full/res']
|
||||
java.srcDirs = ['src/main/java', 'src/full/java']
|
||||
}
|
||||
google_full {
|
||||
res.srcDirs = ['src/main/res', 'src/full/res']
|
||||
java.srcDirs = ['src/main/java', 'src/full/java']
|
||||
}
|
||||
queermotion {
|
||||
res.srcDirs = ['src/main/res', 'src/queermotion/res']
|
||||
java.srcDirs = ['src/main/java', 'src/full/java']
|
||||
}
|
||||
bittube {
|
||||
res.srcDirs = ['src/main/res', 'src/bittube/res']
|
||||
java.srcDirs = ['src/main/java', 'src/full/java']
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,4 +196,8 @@ dependencies {
|
||||
implementation 'org.slf4j:slf4j-simple:1.7.30'
|
||||
|
||||
|
||||
fdroid_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2'
|
||||
google_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2'
|
||||
|
||||
|
||||
}
|
35
app/src/acad/java/app/fedilab/fedilabtube/FedilabTube.java
Normal file
@ -0,0 +1,35 @@
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
47
app/src/acad/java/app/fedilab/fedilabtube/Matomo.java
Normal 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);
|
||||
}
|
||||
}
|
20
app/src/full/java/app/fedilab/fedilabtube/FedilabTube.java
Normal file
@ -0,0 +1,20 @@
|
||||
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>. */
|
||||
|
||||
|
||||
|
||||
public class FedilabTube extends BaseFedilabTube {
|
||||
}
|
41
app/src/full/java/app/fedilab/fedilabtube/Matomo.java
Normal file
@ -0,0 +1,41 @@
|
||||
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;
|
||||
|
||||
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
public class Matomo {
|
||||
|
||||
public static void sendScreen(Context _mcontext, String path, String title) {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@ -74,6 +74,7 @@ import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
|
||||
public class AllPlaylistsActivity extends AppCompatActivity implements PlaylistAdapter.AllPlaylistRemoved {
|
||||
|
||||
|
||||
private static final int PICK_AVATAR = 467;
|
||||
PlaylistAdapter playlistAdapter;
|
||||
private HashMap<Integer, String> privacyToSend;
|
||||
private String idChannel;
|
||||
@ -81,7 +82,6 @@ public class AllPlaylistsActivity extends AppCompatActivity implements PlaylistA
|
||||
private Playlist playlistToEdit;
|
||||
private List<ChannelData.Channel> myChannels;
|
||||
private ChannelData.Channel selectedChannel;
|
||||
private static final int PICK_AVATAR = 467;
|
||||
private AddPlaylistBinding bindingDialog;
|
||||
private Uri inputData;
|
||||
private ActivityAllPlaylistBinding binding;
|
||||
@ -197,7 +197,7 @@ public class AllPlaylistsActivity extends AppCompatActivity implements PlaylistA
|
||||
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
|
||||
startActivityForResult(intent, PICK_AVATAR);
|
||||
});
|
||||
Helper.loadGiF(AllPlaylistsActivity.this, playlistParam.getThumbnailPath(), bindingDialog.profilePicture);
|
||||
Helper.loadGiF(AllPlaylistsActivity.this, playlistParam != null ? playlistParam.getThumbnailPath() : null, bindingDialog.profilePicture);
|
||||
alertDialog.setOnShowListener(dialogInterface -> {
|
||||
|
||||
Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
|
@ -35,7 +35,7 @@ import app.fedilab.fedilabtube.helper.ThemeHelper;
|
||||
import app.fedilab.fedilabtube.services.GlobalUploadObserver;
|
||||
import app.fedilab.fedilabtube.worker.WorkHelper;
|
||||
|
||||
public class FedilabTube extends MultiDexApplication {
|
||||
public class BaseFedilabTube extends MultiDexApplication {
|
||||
|
||||
static String UPLOAD_CHANNEL_ID = "upload_info_peertube";
|
||||
|
||||
@ -48,12 +48,12 @@ public class FedilabTube extends MultiDexApplication {
|
||||
Configuration myConfig = new Configuration.Builder()
|
||||
.setMinimumLoggingLevel(android.util.Log.INFO)
|
||||
.build();
|
||||
WorkManager.initialize(FedilabTube.this, myConfig);
|
||||
WorkManager.initialize(BaseFedilabTube.this, myConfig);
|
||||
if (interval >= 15) {
|
||||
WorkHelper.fetchNotifications(this, interval);
|
||||
}
|
||||
createNotificationChannel();
|
||||
UploadServiceConfig.initialize(FedilabTube.this, UPLOAD_CHANNEL_ID, true);
|
||||
UploadServiceConfig.initialize(BaseFedilabTube.this, UPLOAD_CHANNEL_ID, true);
|
||||
|
||||
new GlobalRequestObserver(this, new GlobalUploadObserver());
|
||||
}
|
||||
@ -63,7 +63,7 @@ public class FedilabTube extends MultiDexApplication {
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
|
||||
MultiDex.install(FedilabTube.this);
|
||||
MultiDex.install(BaseFedilabTube.this);
|
||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
int themePref = sharedpreferences.getInt(Helper.SET_THEME, Helper.DEFAULT_MODE);
|
||||
ThemeHelper.switchTo(themePref);
|
@ -26,6 +26,8 @@ import android.util.Patterns;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -35,6 +37,9 @@ import androidx.core.content.ContextCompat;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
|
||||
import app.fedilab.fedilabtube.client.entities.Error;
|
||||
@ -56,6 +61,7 @@ public class LoginActivity extends AppCompatActivity {
|
||||
private static String client_id;
|
||||
private static String client_secret;
|
||||
private ActivityLoginBinding binding;
|
||||
private String acadInstance;
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
@ -117,69 +123,59 @@ public class LoginActivity extends AppCompatActivity {
|
||||
if (!hasFocus) {
|
||||
if (binding.loginUid.getText() != null && android.util.Patterns.EMAIL_ADDRESS.matcher(binding.loginUid.getText().toString().trim()).matches()) {
|
||||
String[] emailArray = binding.loginUid.getText().toString().split("@");
|
||||
if (emailArray.length > 1 && Arrays.asList(HelperAcadInstance.openid).contains(emailArray[1])) {
|
||||
if (emailArray.length > 1) {
|
||||
binding.loginButton.callOnClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
binding.loginUidContainer.setVisibility(View.GONE);
|
||||
binding.loginPasswdContainer.setVisibility(View.GONE);
|
||||
binding.loginInstanceContainer.setVisibility(View.GONE);
|
||||
binding.createAnAccountPeertube.setVisibility(View.GONE);
|
||||
binding.instancePickerTitle.setVisibility(View.VISIBLE);
|
||||
binding.instancePicker.setVisibility(View.VISIBLE);
|
||||
|
||||
HashMap<String, String> instancesMap = new HashMap<>(HelperAcadInstance.instances_themes);
|
||||
Iterator<Map.Entry<String, String>> it = instancesMap.entrySet().iterator();
|
||||
String[] academiesKey = new String[HelperAcadInstance.instances_themes.size()];
|
||||
String[] academiesValue = new String[HelperAcadInstance.instances_themes.size()];
|
||||
String acad = HelperInstance.getLiveInstance(LoginActivity.this);
|
||||
int position = 0;
|
||||
int i = 0;
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, String> pair = it.next();
|
||||
academiesKey[i] = pair.getKey();
|
||||
academiesValue[i] = pair.getValue();
|
||||
if (pair.getValue().compareTo(acad) == 0) {
|
||||
position = i;
|
||||
}
|
||||
it.remove();
|
||||
i++;
|
||||
}
|
||||
binding.instancePicker.setSelection(position, true);
|
||||
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(LoginActivity.this,
|
||||
android.R.layout.simple_spinner_dropdown_item, academiesKey);
|
||||
binding.instancePicker.setAdapter(adapterChannel);
|
||||
binding.instancePicker.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
acadInstance = academiesValue[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
binding.loginButton.setOnClickListener(v -> {
|
||||
|
||||
if (binding.loginUid.getText() != null && binding.loginUid.getText().toString().contains("@") && !android.util.Patterns.EMAIL_ADDRESS.matcher(binding.loginUid.getText().toString().trim()).matches()) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.email_error)).show();
|
||||
return;
|
||||
}
|
||||
binding.loginButton.setEnabled(false);
|
||||
String instance, host;
|
||||
if (!BuildConfig.full_instances) {
|
||||
String[] emailArray = binding.loginUid.getText().toString().split("@");
|
||||
if (emailArray.length > 1 && !Arrays.asList(HelperAcadInstance.valideEmails).contains(emailArray[1])) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.email_error_domain, emailArray[1])).show();
|
||||
binding.loginButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
host = emailArray[1];
|
||||
instance = HelperInstance.getPeertubeUrl(host);
|
||||
} else {
|
||||
if (binding.loginInstance.getText() == null || binding.loginInstance.getText().toString().trim().length() == 0) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show();
|
||||
binding.loginButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
instance = host = binding.loginInstance.getText().toString().trim().toLowerCase();
|
||||
}
|
||||
|
||||
if (instance.startsWith("http")) {
|
||||
try {
|
||||
URL url = new URL(instance);
|
||||
instance = url.getHost();
|
||||
host = instance;
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (instance.endsWith("/")) {
|
||||
try {
|
||||
URL url = new URL("https://" + instance);
|
||||
instance = url.getHost();
|
||||
host = instance;
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!Patterns.WEB_URL.matcher("https://" + instance).matches()) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show();
|
||||
binding.loginButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
String finalInstance = instance;
|
||||
String finalHost = host;
|
||||
if (Arrays.asList(HelperAcadInstance.openid).contains(host) && !BuildConfig.full_instances) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(null, null, null, null);
|
||||
Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, acadInstance, null).oauthClient(null, null, null, null);
|
||||
if (oauth == null) {
|
||||
runOnUiThread(() -> {
|
||||
binding.loginButton.setEnabled(true);
|
||||
@ -196,7 +192,7 @@ public class LoginActivity extends AppCompatActivity {
|
||||
editor.apply();
|
||||
Intent intent = new Intent(LoginActivity.this, WebviewConnectActivity.class);
|
||||
Bundle b = new Bundle();
|
||||
b.putString("url", "https://" + HelperInstance.getPeertubeUrl(finalHost) + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect");
|
||||
b.putString("url", "https://" + acadInstance + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect");
|
||||
intent.putExtras(b);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
@ -210,50 +206,100 @@ public class LoginActivity extends AppCompatActivity {
|
||||
|
||||
}).start();
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.WEBSITE_VALUE, Helper.OAUTH_SCOPES_PEERTUBE, Helper.WEBSITE_VALUE);
|
||||
if (oauth == null) {
|
||||
runOnUiThread(() -> {
|
||||
binding.loginButton.setEnabled(true);
|
||||
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
|
||||
});
|
||||
if (binding.loginUid.getText() != null && binding.loginUid.getText().toString().contains("@") && !android.util.Patterns.EMAIL_ADDRESS.matcher(binding.loginUid.getText().toString().trim()).matches()) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.email_error)).show();
|
||||
return;
|
||||
}
|
||||
binding.loginButton.setEnabled(false);
|
||||
String instance, host;
|
||||
if (!BuildConfig.full_instances) {
|
||||
String[] emailArray = binding.loginUid.getText().toString().split("@");
|
||||
if (emailArray.length > 1 && !Arrays.asList(HelperAcadInstance.valideEmails).contains(emailArray[1])) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.email_error_domain, emailArray[1])).show();
|
||||
binding.loginButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
client_id = oauth.getClient_id();
|
||||
client_secret = oauth.getClient_secret();
|
||||
|
||||
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();
|
||||
OauthParams oauthParams = new OauthParams();
|
||||
oauthParams.setClient_id(client_id);
|
||||
oauthParams.setClient_secret(client_secret);
|
||||
oauthParams.setGrant_type("password");
|
||||
oauthParams.setScope("user");
|
||||
oauthParams.setUsername(binding.loginUid.getText().toString().trim());
|
||||
if (binding.loginPasswd.getText() != null) {
|
||||
oauthParams.setPassword(binding.loginPasswd.getText().toString());
|
||||
instance = HelperInstance.getLiveInstance(LoginActivity.this);
|
||||
host = instance;
|
||||
} else {
|
||||
if (binding.loginInstance.getText() == null || binding.loginInstance.getText().toString().trim().length() == 0) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show();
|
||||
binding.loginButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
instance = host = binding.loginInstance.getText().toString().trim().toLowerCase();
|
||||
}
|
||||
|
||||
if (instance.startsWith("http")) {
|
||||
try {
|
||||
Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams);
|
||||
proceedLogin(token, finalHost);
|
||||
} catch (final Exception | Error e) {
|
||||
oauthParams.setUsername(binding.loginUid.getText().toString().toLowerCase().trim());
|
||||
URL url = new URL(instance);
|
||||
instance = url.getHost();
|
||||
host = instance;
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (instance.endsWith("/")) {
|
||||
try {
|
||||
URL url = new URL("https://" + instance);
|
||||
instance = url.getHost();
|
||||
host = instance;
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!Patterns.WEB_URL.matcher("https://" + instance).matches()) {
|
||||
Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show();
|
||||
binding.loginButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
String finalInstance = instance;
|
||||
String finalHost = host;
|
||||
if (BuildConfig.full_instances) {
|
||||
new Thread(() -> {
|
||||
Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.WEBSITE_VALUE, Helper.OAUTH_SCOPES_PEERTUBE, Helper.WEBSITE_VALUE);
|
||||
if (oauth == null) {
|
||||
runOnUiThread(() -> {
|
||||
binding.loginButton.setEnabled(true);
|
||||
Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
client_id = oauth.getClient_id();
|
||||
client_secret = oauth.getClient_secret();
|
||||
|
||||
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();
|
||||
OauthParams oauthParams = new OauthParams();
|
||||
oauthParams.setClient_id(client_id);
|
||||
oauthParams.setClient_secret(client_secret);
|
||||
oauthParams.setGrant_type("password");
|
||||
oauthParams.setScope("user");
|
||||
oauthParams.setUsername(binding.loginUid.getText().toString().trim());
|
||||
if (binding.loginPasswd.getText() != null) {
|
||||
oauthParams.setPassword(binding.loginPasswd.getText().toString());
|
||||
}
|
||||
try {
|
||||
Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams);
|
||||
proceedLogin(token, finalHost);
|
||||
} catch (Error error) {
|
||||
Error.displayError(LoginActivity.this, error);
|
||||
error.printStackTrace();
|
||||
runOnUiThread(() -> binding.loginButton.setEnabled(true));
|
||||
} catch (final Exception | Error e) {
|
||||
oauthParams.setUsername(binding.loginUid.getText().toString().toLowerCase().trim());
|
||||
try {
|
||||
Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams);
|
||||
proceedLogin(token, finalHost);
|
||||
} catch (Error error) {
|
||||
Error.displayError(LoginActivity.this, error);
|
||||
error.printStackTrace();
|
||||
runOnUiThread(() -> binding.loginButton.setEnabled(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,11 @@ import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
@ -80,6 +83,7 @@ import app.fedilab.fedilabtube.databinding.ActivityMainBinding;
|
||||
import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment;
|
||||
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
|
||||
import app.fedilab.fedilabtube.helper.Helper;
|
||||
import app.fedilab.fedilabtube.helper.HelperAcadInstance;
|
||||
import app.fedilab.fedilabtube.helper.HelperInstance;
|
||||
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
|
||||
import app.fedilab.fedilabtube.helper.SwitchAccountHelper;
|
||||
@ -97,7 +101,7 @@ import su.litvak.chromecast.api.v2.MediaStatus;
|
||||
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.NORMAL;
|
||||
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.SURFING;
|
||||
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
|
||||
import static app.fedilab.fedilabtube.helper.HelperAcadInstance.academies;
|
||||
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements ChromeCastsListener {
|
||||
|
||||
@ -107,16 +111,53 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
public static UserMe userMe;
|
||||
public static InstanceData.InstanceConfig instanceConfig;
|
||||
public static TypeOfConnection typeOfConnection;
|
||||
public static List<ChromeCast> chromeCasts;
|
||||
public static ChromeCast chromeCast;
|
||||
public static boolean chromecastActivated = false;
|
||||
private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
|
||||
private DisplayOverviewFragment overviewFragment;
|
||||
private ActivityMainBinding binding;
|
||||
private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
|
||||
= item -> {
|
||||
int itemId = item.getItemId();
|
||||
String type = null;
|
||||
if (itemId == R.id.navigation_discover) {
|
||||
setTitleCustom(R.string.title_discover);
|
||||
binding.viewpager.setCurrentItem(0);
|
||||
type = HelperAcadInstance.DISCOVER;
|
||||
} else if (itemId == R.id.navigation_subscription) {
|
||||
binding.viewpager.setCurrentItem(1);
|
||||
setTitleCustom(R.string.subscriptions);
|
||||
type = HelperAcadInstance.SUBSCRIPTIONS;
|
||||
} else if (itemId == R.id.navigation_trending) {
|
||||
setTitleCustom(R.string.title_trending);
|
||||
if (Helper.isLoggedIn(MainActivity.this)) {
|
||||
binding.viewpager.setCurrentItem(2);
|
||||
} else {
|
||||
binding.viewpager.setCurrentItem(1);
|
||||
}
|
||||
type = HelperAcadInstance.TRENDING;
|
||||
} else if (itemId == R.id.navigation_most_liked) {
|
||||
setTitleCustom(R.string.title_most_liked);
|
||||
binding.viewpager.setCurrentItem(2);
|
||||
type = HelperAcadInstance.MOSTLIKED;
|
||||
} else if (itemId == R.id.navigation_recently_added) {
|
||||
setTitleCustom(R.string.title_recently_added);
|
||||
binding.viewpager.setCurrentItem(3);
|
||||
type = HelperAcadInstance.RECENTLY_ADDED;
|
||||
} else if (itemId == R.id.navigation_local) {
|
||||
setTitleCustom(R.string.title_local);
|
||||
binding.viewpager.setCurrentItem(4);
|
||||
type = HelperAcadInstance.LOCAL;
|
||||
}
|
||||
if (type != null) {
|
||||
Matomo.sendScreen(MainActivity.this, "TIMELINE", type);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
private BroadcastReceiver manage_chromecast;
|
||||
public static List<ChromeCast> chromeCasts;
|
||||
public static ChromeCast chromeCast;
|
||||
private VideoData.Video castedTube;
|
||||
|
||||
public static boolean chromecastActivated = false;
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) {
|
||||
final SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
@ -190,35 +231,6 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
}
|
||||
}
|
||||
|
||||
private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
|
||||
= item -> {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.navigation_discover) {
|
||||
setTitleCustom(R.string.title_discover);
|
||||
binding.viewpager.setCurrentItem(0);
|
||||
} else if (itemId == R.id.navigation_subscription) {
|
||||
binding.viewpager.setCurrentItem(1);
|
||||
setTitleCustom(R.string.subscriptions);
|
||||
} else if (itemId == R.id.navigation_trending) {
|
||||
setTitleCustom(R.string.title_trending);
|
||||
if (Helper.isLoggedIn(MainActivity.this)) {
|
||||
binding.viewpager.setCurrentItem(2);
|
||||
} else {
|
||||
binding.viewpager.setCurrentItem(1);
|
||||
}
|
||||
} else if (itemId == R.id.navigation_most_liked) {
|
||||
setTitleCustom(R.string.title_most_liked);
|
||||
binding.viewpager.setCurrentItem(2);
|
||||
} else if (itemId == R.id.navigation_recently_added) {
|
||||
setTitleCustom(R.string.title_recently_added);
|
||||
binding.viewpager.setCurrentItem(3);
|
||||
} else if (itemId == R.id.navigation_local) {
|
||||
setTitleCustom(R.string.title_local);
|
||||
binding.viewpager.setCurrentItem(4);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
@Override
|
||||
public void newChromeCastDiscovered(ChromeCast chromeCast) {
|
||||
if (chromeCasts == null) {
|
||||
@ -341,9 +353,8 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
|
||||
typeOfConnection = TypeOfConnection.UNKNOWN;
|
||||
|
||||
BottomNavigationView navView = findViewById(R.id.nav_view);
|
||||
|
||||
navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
|
||||
binding.navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
@ -382,6 +393,8 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
}
|
||||
binding.viewpager.setOffscreenPageLimit(5);
|
||||
|
||||
Matomo.sendEvent(MainActivity.this, "UTILISATEUR", "DEMARRAGE", HelperInstance.getLiveInstance(MainActivity.this), Helper.isLoggedIn(MainActivity.this) ? 1 : 0);
|
||||
|
||||
|
||||
binding.viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
@ -416,12 +429,11 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
setTitleCustom(R.string.title_discover);
|
||||
|
||||
if (Helper.isLoggedIn(MainActivity.this)) {
|
||||
|
||||
navView.inflateMenu(R.menu.bottom_nav_menu_connected);
|
||||
binding.navView.inflateMenu(R.menu.bottom_nav_menu_connected);
|
||||
refreshToken();
|
||||
|
||||
} else {
|
||||
navView.inflateMenu(R.menu.bottom_nav_menu);
|
||||
binding.navView.inflateMenu(R.menu.bottom_nav_menu);
|
||||
}
|
||||
peertubeInformation = new PeertubeInformation();
|
||||
peertubeInformation.setCategories(new LinkedHashMap<>());
|
||||
@ -566,25 +578,7 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
oauthParams.setAccess_token(account.getToken());
|
||||
try {
|
||||
Token token = new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams);
|
||||
if (token == null && Helper.instanceOnline(instance)) {
|
||||
runOnUiThread(() -> {
|
||||
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
|
||||
alt_bld.setTitle(R.string.refresh_token_failed);
|
||||
alt_bld.setMessage(R.string.refresh_token_failed_message);
|
||||
alt_bld.setNegativeButton(R.string.action_logout, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
Helper.logoutCurrentUser(MainActivity.this, finalAccount);
|
||||
});
|
||||
alt_bld.setPositiveButton(R.string._retry, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
refreshToken();
|
||||
});
|
||||
AlertDialog alert = alt_bld.create();
|
||||
alert.show();
|
||||
|
||||
});
|
||||
return;
|
||||
} else if (token == null) {
|
||||
if (token == null) {
|
||||
return;
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
@ -622,7 +616,22 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
}
|
||||
instanceConfig = new RetrofitPeertubeAPI(MainActivity.this).getConfigInstance();
|
||||
} catch (Error error) {
|
||||
runOnUiThread(() -> Helper.logoutCurrentUser(MainActivity.this, finalAccount));
|
||||
runOnUiThread(() -> {
|
||||
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
|
||||
alt_bld.setTitle(R.string.refresh_token_failed);
|
||||
alt_bld.setMessage(R.string.refresh_token_failed_message);
|
||||
alt_bld.setNegativeButton(R.string.action_logout, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
Helper.logoutCurrentUser(MainActivity.this, finalAccount);
|
||||
});
|
||||
alt_bld.setPositiveButton(R.string._retry, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
refreshToken();
|
||||
});
|
||||
AlertDialog alert = alt_bld.create();
|
||||
alert.show();
|
||||
|
||||
});
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -772,13 +781,16 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
String type = null;
|
||||
String action = "TIMELINE";
|
||||
if (item.getItemId() == R.id.action_change_instance) {
|
||||
if (BuildConfig.full_instances) {
|
||||
showRadioButtonDialogFullInstances(MainActivity.this, false);
|
||||
} else {
|
||||
showRadioButtonDialog();
|
||||
}
|
||||
return true;
|
||||
action = "CHANGE_INSTANCE";
|
||||
type = "";
|
||||
} else if (item.getItemId() == R.id.action_settings) {
|
||||
Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
@ -794,32 +806,30 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
}
|
||||
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, VideosTimelineActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("type", TimelineVM.TimelineType.MY_VIDEOS);
|
||||
intent.putExtras(bundle);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
type = HelperAcadInstance.MYVIDEOS;
|
||||
} else if (item.getItemId() == R.id.action_history) {
|
||||
Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("type", TimelineVM.TimelineType.HISTORY);
|
||||
intent.putExtras(bundle);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
type = HelperAcadInstance.HISTORY;
|
||||
} else if (item.getItemId() == R.id.action_most_liked) {
|
||||
Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("type", TimelineVM.TimelineType.MOST_LIKED);
|
||||
intent.putExtras(bundle);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
type = HelperAcadInstance.MOSTLIKED;
|
||||
} else if (item.getItemId() == R.id.action_playlist) {
|
||||
Intent intent;
|
||||
if (Helper.isLoggedIn(MainActivity.this)) {
|
||||
@ -828,15 +838,12 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
intent = new Intent(MainActivity.this, AllLocalPlaylistsActivity.class);
|
||||
}
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_sepia_search) {
|
||||
Intent intent = new Intent(MainActivity.this, SepiaSearchActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_about) {
|
||||
Intent intent = new Intent(MainActivity.this, AboutActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_incognito) {
|
||||
item.setChecked(!item.isChecked());
|
||||
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
@ -855,8 +862,10 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
}).start();
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
if (type != null) {
|
||||
Matomo.sendScreen(MainActivity.this, action, type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -884,14 +893,23 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String acad = HelperInstance.getLiveInstance(MainActivity.this);
|
||||
int i = 0;
|
||||
for (String item : academies) {
|
||||
if (HelperInstance.getPeertubeUrl(item).compareTo(acad) == 0) {
|
||||
break;
|
||||
HashMap<String, String> instancesMap = new HashMap<>(HelperAcadInstance.instances_themes);
|
||||
Iterator<Map.Entry<String, String>> it = instancesMap.entrySet().iterator();
|
||||
String[] academiesKey = new String[HelperAcadInstance.instances_themes.size()];
|
||||
String[] academiesValue = new String[HelperAcadInstance.instances_themes.size()];
|
||||
int position = 0;
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, String> pair = it.next();
|
||||
academiesKey[i] = pair.getKey();
|
||||
academiesValue[i] = pair.getValue();
|
||||
if (pair.getValue().compareTo(acad) == 0) {
|
||||
position = i;
|
||||
}
|
||||
it.remove();
|
||||
i++;
|
||||
}
|
||||
alt_bld.setSingleChoiceItems(academies, i, (dialog, item) -> {
|
||||
String newInstance = academies[item];
|
||||
alt_bld.setSingleChoiceItems(academiesKey, position, (dialog, item) -> {
|
||||
String newInstance = academiesValue[item];
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putString(Helper.PREF_INSTANCE, newInstance);
|
||||
editor.commit();
|
||||
@ -918,6 +936,12 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
}
|
||||
}
|
||||
|
||||
public enum TypeOfConnection {
|
||||
UNKNOWN,
|
||||
NORMAL,
|
||||
SURFING
|
||||
}
|
||||
|
||||
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
ScreenSlidePagerAdapter(FragmentManager fm) {
|
||||
@ -962,10 +986,4 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TypeOfConnection {
|
||||
UNKNOWN,
|
||||
NORMAL,
|
||||
SURFING
|
||||
}
|
||||
}
|
@ -96,6 +96,7 @@ import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer2.ui.DefaultTimeBar;
|
||||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
@ -103,6 +104,7 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.android.exoplayer2.video.VideoListener;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -233,7 +235,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
|
||||
@Override
|
||||
public void onStreamStarted(Torrent torrent) {
|
||||
startStream(torrent.getVideoFile().getAbsolutePath(), null, autoPlay, -1, null, null, true);
|
||||
startStream(peertube, torrent.getVideoFile().getAbsolutePath(), null, autoPlay, -1, null, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -315,7 +317,10 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
sepiaSearch = b.getBoolean("sepia_search", false);
|
||||
peertube = b.getParcelable("video");
|
||||
}
|
||||
|
||||
new Thread(() -> {
|
||||
String videoId = peertube != null ? peertube.getUuid() : videoUuid;
|
||||
new RetrofitPeertubeAPI(PeertubeActivity.this).postView(videoId);
|
||||
}).start();
|
||||
willPlayFromIntent = manageIntentUrl(intent);
|
||||
|
||||
binding.peertubeDescriptionMore.setOnClickListener(v -> {
|
||||
@ -486,6 +491,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
return;
|
||||
}
|
||||
peertube = apiResponse.getPeertubes().get(0);
|
||||
Matomo.sendScreen(PeertubeActivity.this, "VIDEO_REGARDEE", peertube.getUuid());
|
||||
if (peertube.isNsfw()) {
|
||||
binding.videoSensitive.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
@ -958,7 +964,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
binding.loader.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
if (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().get(0) == null || apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this) == null) {
|
||||
if (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().get(0) == null || (!apiResponse.getPeertubes().get(0).isLive() && apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this) == null)) {
|
||||
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
binding.loader.setVisibility(View.GONE);
|
||||
return;
|
||||
@ -974,6 +980,23 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
userHistory.setCurrentTime(previousPositionHistory);
|
||||
peertube.setUserHistory(userHistory);
|
||||
|
||||
|
||||
PlayerControlView controlView = binding.doubleTapPlayerView.findViewById(R.id.exo_controller);
|
||||
DefaultTimeBar exo_progress = controlView.findViewById(R.id.exo_progress);
|
||||
TextView exo_duration = controlView.findViewById(R.id.exo_duration);
|
||||
TextView exo_live_badge = controlView.findViewById(R.id.exo_live_badge);
|
||||
if (peertube.isLive()) {
|
||||
exo_progress.setVisibility(View.INVISIBLE);
|
||||
exo_duration.setVisibility(View.GONE);
|
||||
exo_live_badge.setVisibility(View.VISIBLE);
|
||||
exo_live_badge.setText(R.string.live);
|
||||
exo_live_badge.setBackgroundResource(R.drawable.rounded_live);
|
||||
} else {
|
||||
exo_progress.setVisibility(View.VISIBLE);
|
||||
exo_live_badge.setVisibility(View.GONE);
|
||||
exo_duration.setBackground(null);
|
||||
}
|
||||
|
||||
if (peertube.getUserHistory() != null) {
|
||||
position = peertube.getUserHistory().getCurrentTime() * 1000;
|
||||
}
|
||||
@ -1025,7 +1048,13 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
LinkedHashMap<Integer, String> categoryInit = new LinkedHashMap<>(peertubeInformation.getCategories());
|
||||
info_category.setText(categoryInit.get(peertube.getCategory().getId()));
|
||||
|
||||
info_duration.setText(Helper.secondsToString(peertube.getDuration()));
|
||||
if (peertube.isLive()) {
|
||||
info_duration.setText(R.string.live);
|
||||
info_duration.setBackgroundResource(R.drawable.rounded_live);
|
||||
} else {
|
||||
info_duration.setText(Helper.secondsToString(peertube.getDuration()));
|
||||
}
|
||||
|
||||
String format = DateFormat.getDateInstance(DateFormat.LONG).format(peertube.getPublishedAt());
|
||||
info_published_at.setText(format);
|
||||
List<String> tags = peertube.getTags();
|
||||
@ -1169,8 +1198,9 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
binding.doubleTapPlayerView.setPlayer(player);
|
||||
binding.loader.setVisibility(View.GONE);
|
||||
startStream(
|
||||
apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this),
|
||||
apiResponse.getPeertubes().get(0).getStreamingPlaylists().size() > 0 ? apiResponse.getPeertubes().get(0).getStreamingPlaylists().get(0).getPlaylistUrl() : null,
|
||||
apiResponse.getPeertubes().get(0),
|
||||
null,
|
||||
null,
|
||||
autoPlay, position, null, null, true);
|
||||
player.prepare();
|
||||
player.setPlayWhenReady(autoPlay);
|
||||
@ -1259,7 +1289,8 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
}
|
||||
|
||||
|
||||
private void stream(String videoURL, String streamingPlaylistsURLS, boolean autoPlay, long position, Uri subtitles, String lang) {
|
||||
private void stream(VideoData.Video video, String resolution, boolean autoPlay, long position, Uri subtitles, String lang) {
|
||||
String videoURL = video.getFileUrl(resolution, PeertubeActivity.this);
|
||||
if (videoURL != null && !videoURL.endsWith("m3u8")) {
|
||||
if (videoURL.endsWith(".torrent")) {
|
||||
torrentStream.startStream(videoURL);
|
||||
@ -1298,10 +1329,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (streamingPlaylistsURLS == null && videoURL != null) {
|
||||
streamingPlaylistsURLS = videoURL;
|
||||
}
|
||||
MediaItem mediaItem = new MediaItem.Builder().setUri(Uri.parse(streamingPlaylistsURLS)).build();
|
||||
MediaItem mediaItem = new MediaItem.Builder().setUri(Uri.parse(videoURL)).build();
|
||||
HlsMediaSource hlsMediaSource = new HlsMediaSource.Factory(new DefaultHttpDataSourceFactory(System.getProperty("http.agent")))
|
||||
.createMediaSource(mediaItem);
|
||||
player.setMediaSource(hlsMediaSource);
|
||||
@ -1340,8 +1368,21 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
}
|
||||
}
|
||||
|
||||
private void startStream(String videoURL, String streamingPlaylistsURLS, boolean autoPlay, long position, Uri subtitles, String lang, boolean promptNSFW) {
|
||||
private void startStream(VideoData.Video video, String torrentLocal, String resolution, boolean autoPlay, long position, Uri subtitles, String lang, boolean promptNSFW) {
|
||||
|
||||
String videoURL;
|
||||
if (torrentLocal != null) {
|
||||
videoURL = torrentLocal;
|
||||
} else {
|
||||
videoURL = peertube.getFileUrl(resolution, PeertubeActivity.this);
|
||||
}
|
||||
if (peertube != null && peertube.isWaitTranscoding() && peertube.isLive()) {
|
||||
View parentLayout = findViewById(android.R.id.content);
|
||||
Snackbar snackbar = Snackbar.make(parentLayout, R.string.live_not_started, Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.setAction(R.string.close, view -> finish());
|
||||
snackbar.show();
|
||||
return;
|
||||
}
|
||||
chromeCastVideoURL = videoURL;
|
||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
|
||||
String nsfwAction = sharedpreferences.getString(getString(R.string.set_video_sensitive_choice), Helper.BLUR);
|
||||
@ -1357,13 +1398,13 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
finish();
|
||||
});
|
||||
dialogBuilder.setPositiveButton(R.string.play, (dialog, id) -> {
|
||||
stream(videoURL, streamingPlaylistsURLS, autoPlay, position, subtitles, lang);
|
||||
stream(video, resolution, autoPlay, position, subtitles, lang);
|
||||
dialog.dismiss();
|
||||
});
|
||||
alertDialog = dialogBuilder.create();
|
||||
alertDialog.show();
|
||||
} else {
|
||||
stream(videoURL, streamingPlaylistsURLS, autoPlay, position, subtitles, lang);
|
||||
stream(video, resolution, autoPlay, position, subtitles, lang);
|
||||
}
|
||||
|
||||
|
||||
@ -1591,6 +1632,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
binding.peertubeInformationContainer.setVisibility(View.GONE);
|
||||
@ -1743,8 +1785,9 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
binding.doubleTapPlayerView.setPlayer(player);
|
||||
binding.loader.setVisibility(View.GONE);
|
||||
startStream(
|
||||
peertube.getFileUrl(res, PeertubeActivity.this),
|
||||
peertube.getStreamingPlaylists().size() > 0 ? peertube.getStreamingPlaylists().get(0).getPlaylistUrl() : null,
|
||||
peertube,
|
||||
null,
|
||||
res,
|
||||
true, position, null, null, false);
|
||||
}
|
||||
break;
|
||||
@ -1783,7 +1826,8 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
binding.mediaVideo.player(player);
|
||||
binding.doubleTapPlayerView.setPlayer(player);
|
||||
startStream(
|
||||
peertube.getFileUrl(null, PeertubeActivity.this),
|
||||
peertube,
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
newPosition,
|
||||
@ -1842,7 +1886,6 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void closeSubMenuMenuOptions() {
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
@ -2020,8 +2063,8 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
}
|
||||
} else if (peertube.isCommentsEnabled() && statusAction == REPLY) {
|
||||
if (apiResponse.getComments() != null && apiResponse.getComments().size() > 0) {
|
||||
commentsThread.add(position, apiResponse.getComments().get(0));
|
||||
commentReplyListAdapter.notifyItemInserted(position);
|
||||
commentsThread.add(position + 1, apiResponse.getComments().get(0));
|
||||
commentReplyListAdapter.notifyItemInserted(position + 1);
|
||||
}
|
||||
} else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT) {
|
||||
Toasty.success(PeertubeActivity.this, getString(R.string.successful_report), Toasty.LENGTH_LONG).show();
|
||||
@ -2063,6 +2106,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
openMainMenuOptions();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void setRequestedOrientationCustom(int orientationCustom) {
|
||||
@ -2272,8 +2316,6 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
enum videoOrientation {
|
||||
LANDSCAPE,
|
||||
PORTRAIT
|
||||
|
@ -163,8 +163,7 @@ public class PeertubeRegisterActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
String host = emailArray[1];
|
||||
instance = HelperInstance.getPeertubeUrl(host);
|
||||
instance = HelperInstance.getLiveInstance(PeertubeRegisterActivity.this);
|
||||
}
|
||||
if (instance != null) {
|
||||
instance = instance.toLowerCase().trim();
|
||||
|
@ -37,7 +37,6 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
|
||||
import net.gotev.uploadservice.data.UploadNotificationAction;
|
||||
import net.gotev.uploadservice.data.UploadNotificationConfig;
|
||||
import net.gotev.uploadservice.data.UploadNotificationStatusConfig;
|
||||
|
@ -160,16 +160,14 @@ public class ShowChannelActivity extends AppCompatActivity {
|
||||
if (accounts != null && accounts.size() > 0) {
|
||||
if (accounts.size() > 1) {
|
||||
final OwnAccountsAdapter accountsListAdapter = new OwnAccountsAdapter(ShowChannelActivity.this, accounts);
|
||||
builderSingle.setAdapter(accountsListAdapter, (dialog, which) -> {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
RetrofitPeertubeAPI peertubeAPI = new RetrofitPeertubeAPI(ShowChannelActivity.this, accounts.get(which).getHost(), accounts.get(which).getToken());
|
||||
peertubeAPI.post(FOLLOW, channel.getAcct(), null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
builderSingle.setAdapter(accountsListAdapter, (dialog, which) -> new Thread(() -> {
|
||||
try {
|
||||
RetrofitPeertubeAPI peertubeAPI = new RetrofitPeertubeAPI(ShowChannelActivity.this, accounts.get(which).getHost(), accounts.get(which).getToken());
|
||||
peertubeAPI.post(FOLLOW, channel.getAcct(), null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start());
|
||||
} else {
|
||||
RetrofitPeertubeAPI peertubeAPI = new RetrofitPeertubeAPI(ShowChannelActivity.this, accounts.get(0).getHost(), accounts.get(0).getToken());
|
||||
peertubeAPI.post(FOLLOW, channel.getAcct(), null);
|
||||
@ -362,7 +360,11 @@ public class ShowChannelActivity extends AppCompatActivity {
|
||||
public void manageVIewRelationship(APIResponse apiResponse) {
|
||||
|
||||
if (apiResponse.getError() != null) {
|
||||
Toasty.error(ShowChannelActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
|
||||
if (apiResponse.getError().getError().length() > 500) {
|
||||
Toasty.info(ShowChannelActivity.this, getString(R.string.remote_account), Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toasty.error(ShowChannelActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.relationship = apiResponse.getRelationships();
|
||||
|
@ -122,8 +122,11 @@ public class WebviewConnectActivity extends AppCompatActivity {
|
||||
oauthParams.setClient_id(sharedpreferences.getString(Helper.CLIENT_ID, null));
|
||||
oauthParams.setClient_secret(sharedpreferences.getString(Helper.CLIENT_SECRET, null));
|
||||
oauthParams.setGrant_type("password");
|
||||
oauthParams.setScope("upload");
|
||||
oauthParams.setResponse_type("code");
|
||||
oauthParams.setUsername(username);
|
||||
oauthParams.setExternalAuthToken(externalAuthToken);
|
||||
oauthParams.setPassword(externalAuthToken);
|
||||
String instance = new URL(url).getHost();
|
||||
Token token = null;
|
||||
try {
|
||||
|
@ -103,6 +103,21 @@ public interface PeertubeService {
|
||||
@GET("client/locales/{local}/server.json")
|
||||
Call<Map<String, String>> getTranslations(@Path("local") String local);
|
||||
|
||||
|
||||
//TOKEN
|
||||
//Refresh
|
||||
@FormUrlEncoded
|
||||
@POST("users/token")
|
||||
Call<Token> createOpenIdToken(
|
||||
@Field("client_id") String client_id,
|
||||
@Field("client_secret") String client_secret,
|
||||
@Field("response_type") String response_type,
|
||||
@Field("grant_type") String grant_type,
|
||||
@Field("scope") String scope,
|
||||
@Field("username") String username,
|
||||
@Field("password") String password,
|
||||
@Field("externalAuthToken") String externalAuthToken);
|
||||
|
||||
//TOKEN
|
||||
//Refresh
|
||||
@FormUrlEncoded
|
||||
@ -169,27 +184,55 @@ public interface PeertubeService {
|
||||
//Timelines Authenticated
|
||||
//Subscriber timeline
|
||||
@GET("users/me/subscriptions/videos?sort=-publishedAt")
|
||||
Call<VideoData> getSubscriptionVideos(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("languageOneOf") List<String> languageOneOf);
|
||||
Call<VideoData> getSubscriptionVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String coun,
|
||||
@Query("languageOneOf") List<String> languageOneOf);
|
||||
|
||||
//Overview videos
|
||||
@GET("overviews/videos")
|
||||
Call<OverviewVideo> getOverviewVideos(@Header("Authorization") String credentials, @Query("page") String page, @Query("languageOneOf") List<String> languageOneOf);
|
||||
Call<OverviewVideo> getOverviewVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("page") String page,
|
||||
@Query("nsfw") String nsfw,
|
||||
@Query("languageOneOf") List<String> languageOneOf);
|
||||
|
||||
//Most liked videos
|
||||
@GET("videos?sort=-likes")
|
||||
Call<VideoData> getMostLikedVideos(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("languageOneOf") List<String> languageOneOf);
|
||||
Call<VideoData> getMostLikedVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw,
|
||||
@Query("languageOneOf") List<String> languageOneOf);
|
||||
|
||||
//Trending videos
|
||||
@GET("videos?sort=-trending")
|
||||
Call<VideoData> getTrendingVideos(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("languageOneOf") List<String> languageOneOf);
|
||||
Call<VideoData> getTrendingVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw,
|
||||
@Query("languageOneOf") List<String> languageOneOf);
|
||||
|
||||
//Recently added videos
|
||||
@GET("videos?sort=-publishedAt")
|
||||
Call<VideoData> getRecentlyAddedVideos(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("languageOneOf") List<String> languageOneOf);
|
||||
Call<VideoData> getRecentlyAddedVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw,
|
||||
@Query("languageOneOf") List<String> languageOneOf);
|
||||
|
||||
//Local videos
|
||||
@GET("videos?sort=-publishedAt&filter=local")
|
||||
Call<VideoData> getLocalVideos(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count, @Query("languageOneOf") List<String> languageOneOf);
|
||||
Call<VideoData> getLocalVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw,
|
||||
@Query("languageOneOf") List<String> languageOneOf);
|
||||
|
||||
//History
|
||||
@GET("users/me/history/videos")
|
||||
@ -197,6 +240,7 @@ public interface PeertubeService {
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw,
|
||||
@Query("startDate") String startDate,
|
||||
@Query("endDate") String endDate
|
||||
);
|
||||
@ -211,7 +255,8 @@ public interface PeertubeService {
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("search") String search,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count);
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw);
|
||||
|
||||
//Search channels
|
||||
@GET("search/video-channels")
|
||||
@ -228,7 +273,8 @@ public interface PeertubeService {
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("tagsOneOf") List<String> tagsOneOf,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count);
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw);
|
||||
|
||||
//Get notifications
|
||||
@GET("users/me/notifications")
|
||||
@ -254,9 +300,17 @@ public interface PeertubeService {
|
||||
@GET("users/me/videos?sort=-publishedAt")
|
||||
Call<VideoData> getMyVideos(@Header("Authorization") String credentials, @Query("start") String maxId, @Query("count") String count);
|
||||
|
||||
//Get my video
|
||||
//Get user videos
|
||||
@GET("accounts/{name}/videos?sort=-publishedAt")
|
||||
Call<VideoData> getVideosForAccount(@Path("name") String name, @Query("start") String maxId, @Query("count") String count);
|
||||
Call<VideoData> getVideosForAccount(
|
||||
@Path("name") String name,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw
|
||||
);
|
||||
|
||||
@POST("videos/{id}/views")
|
||||
Call<String> postView(@Path("id") String id);
|
||||
|
||||
@Multipart
|
||||
@PUT("videos/{id}")
|
||||
@ -303,7 +357,11 @@ public interface PeertubeService {
|
||||
Call<ChannelData> getAllChannels();
|
||||
|
||||
@GET("video-channels/{channelHandle}/videos")
|
||||
Call<VideoData> getChannelVideos(@Path("channelHandle") String channelHandle, @Query("start") String maxId, @Query("count") String count);
|
||||
Call<VideoData> getChannelVideos(
|
||||
@Path("channelHandle") String channelHandle,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count,
|
||||
@Query("nsfw") String nsfw);
|
||||
|
||||
@POST("video-channels")
|
||||
Call<ChannelData.ChannelCreation> addChannel(@Header("Authorization") String credentials, @Body ChannelParams channelParams);
|
||||
|
@ -23,6 +23,7 @@ import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
@ -90,7 +91,7 @@ import retrofit2.Response;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
@SuppressWarnings({"unused", "RedundantSuppression", "ConstantConditions"})
|
||||
public class RetrofitPeertubeAPI {
|
||||
|
||||
private final String finalUrl;
|
||||
@ -99,6 +100,7 @@ public class RetrofitPeertubeAPI {
|
||||
private final String count;
|
||||
private String token;
|
||||
private Set<String> selection;
|
||||
private String showNSFWVideos = "both";
|
||||
|
||||
public RetrofitPeertubeAPI(Context context) {
|
||||
_context = context;
|
||||
@ -106,6 +108,14 @@ public class RetrofitPeertubeAPI {
|
||||
finalUrl = "https://" + HelperInstance.getLiveInstance(context) + "/api/v1/";
|
||||
SharedPreferences sharedpreferences = _context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
count = String.valueOf(sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE));
|
||||
String currentSensitive = sharedpreferences.getString(_context.getString(R.string.set_video_sensitive_choice), Helper.BLUR);
|
||||
if (currentSensitive.compareTo(Helper.DO_NOT_LIST) == 0) {
|
||||
showNSFWVideos = "false";
|
||||
} else if (currentSensitive.compareTo(Helper.BLUR) == 0) {
|
||||
showNSFWVideos = "both";
|
||||
} else {
|
||||
showNSFWVideos = "true";
|
||||
}
|
||||
}
|
||||
|
||||
public RetrofitPeertubeAPI(Context context, String instance, String token) {
|
||||
@ -115,18 +125,21 @@ public class RetrofitPeertubeAPI {
|
||||
finalUrl = "https://" + instance + "/api/v1/";
|
||||
SharedPreferences sharedpreferences = _context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
count = String.valueOf(sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE));
|
||||
String currentSensitive = sharedpreferences.getString(_context.getString(R.string.set_video_sensitive_choice), Helper.BLUR);
|
||||
if (currentSensitive.compareTo(Helper.DO_NOT_LIST) == 0) {
|
||||
showNSFWVideos = "false";
|
||||
} else if (currentSensitive.compareTo(Helper.BLUR) == 0) {
|
||||
showNSFWVideos = "both";
|
||||
} else {
|
||||
showNSFWVideos = "true";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void updateCredential(Activity activity, String token, String client_id, String client_secret, String refresh_token, String host) {
|
||||
new Thread(() -> {
|
||||
AccountData.Account account;
|
||||
String instance;
|
||||
if (host.startsWith("tube") || BuildConfig.full_instances) {
|
||||
instance = host;
|
||||
} else {
|
||||
instance = HelperInstance.getPeertubeUrl(host);
|
||||
}
|
||||
String instance = host;
|
||||
try {
|
||||
UserMe userMe = new RetrofitPeertubeAPI(activity, instance, token).verifyCredentials();
|
||||
account = userMe.getAccount();
|
||||
@ -194,6 +207,9 @@ public class RetrofitPeertubeAPI {
|
||||
}
|
||||
|
||||
private PeertubeService initTranslation() {
|
||||
if (!URLUtil.isValidUrl("https://" + instance)) {
|
||||
return null;
|
||||
}
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl("https://" + instance)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
@ -208,7 +224,9 @@ public class RetrofitPeertubeAPI {
|
||||
public Token manageToken(OauthParams oauthParams) throws Error {
|
||||
PeertubeService peertubeService = init();
|
||||
Call<Token> refreshTokenCall = null;
|
||||
if (oauthParams.getGrant_type().compareTo("password") == 0) {
|
||||
if (oauthParams.getExternalAuthToken() != null) {
|
||||
refreshTokenCall = peertubeService.createOpenIdToken(oauthParams.getClient_id(), oauthParams.getClient_secret(), oauthParams.getResponse_type(), oauthParams.getGrant_type(), oauthParams.getScope(), oauthParams.getUsername(), oauthParams.getPassword(), oauthParams.getExternalAuthToken());
|
||||
} else if (oauthParams.getGrant_type().compareTo("password") == 0) {
|
||||
refreshTokenCall = peertubeService.createToken(oauthParams.getClient_id(), oauthParams.getClient_secret(), oauthParams.getGrant_type(), oauthParams.getUsername(), oauthParams.getPassword());
|
||||
} else if (oauthParams.getGrant_type().compareTo("refresh_token") == 0) {
|
||||
refreshTokenCall = peertubeService.refreshToken(oauthParams.getClient_id(), oauthParams.getClient_secret(), oauthParams.getRefresh_token(), oauthParams.getGrant_type());
|
||||
@ -245,6 +263,19 @@ public class RetrofitPeertubeAPI {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* POST a view count for a video
|
||||
*/
|
||||
public void postView(String videoUuid) {
|
||||
PeertubeService peertubeService = init();
|
||||
Call<String> postViewCall = peertubeService.postView(videoUuid);
|
||||
try {
|
||||
Response<String> dd = postViewCall.execute();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve notifications
|
||||
*
|
||||
@ -335,7 +366,7 @@ public class RetrofitPeertubeAPI {
|
||||
public APIResponse getVideosForChannel(String channelId, String max_id) {
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
PeertubeService peertubeService = init();
|
||||
Call<VideoData> videoCall = peertubeService.getChannelVideos(channelId, max_id, count);
|
||||
Call<VideoData> videoCall = peertubeService.getChannelVideos(channelId, max_id, count, showNSFWVideos);
|
||||
if (videoCall != null) {
|
||||
try {
|
||||
Response<VideoData> response = videoCall.execute();
|
||||
@ -380,7 +411,7 @@ public class RetrofitPeertubeAPI {
|
||||
public APIResponse getHistory(String max_id, String startDate, String endDate) {
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
PeertubeService peertubeService = init();
|
||||
Call<VideoData> videoCall = peertubeService.getHistory(getToken(), max_id, count, startDate, endDate);
|
||||
Call<VideoData> videoCall = peertubeService.getHistory(getToken(), max_id, count, showNSFWVideos, startDate, endDate);
|
||||
if (videoCall != null) {
|
||||
try {
|
||||
Response<VideoData> response = videoCall.execute();
|
||||
@ -409,29 +440,29 @@ public class RetrofitPeertubeAPI {
|
||||
videoCall = peertubeService.getMyVideos(getToken(), max_id, count);
|
||||
break;
|
||||
case ACCOUNT_VIDEOS:
|
||||
videoCall = peertubeService.getVideosForAccount(forAccount, max_id, count);
|
||||
videoCall = peertubeService.getVideosForAccount(forAccount, max_id, count, showNSFWVideos);
|
||||
break;
|
||||
case SUBSCRIBTIONS:
|
||||
if (forAccount == null) {
|
||||
videoCall = peertubeService.getSubscriptionVideos(getToken(), max_id, count, filter);
|
||||
} else {
|
||||
videoCall = peertubeService.getChannelVideos(forAccount, max_id, count);
|
||||
videoCall = peertubeService.getChannelVideos(forAccount, max_id, count, showNSFWVideos);
|
||||
}
|
||||
break;
|
||||
case MOST_LIKED:
|
||||
videoCall = peertubeService.getMostLikedVideos(getToken(), max_id, count, filter);
|
||||
videoCall = peertubeService.getMostLikedVideos(getToken(), max_id, count, showNSFWVideos, filter);
|
||||
break;
|
||||
case LOCAL:
|
||||
videoCall = peertubeService.getLocalVideos(getToken(), max_id, count, filter);
|
||||
videoCall = peertubeService.getLocalVideos(getToken(), max_id, count, showNSFWVideos, filter);
|
||||
break;
|
||||
case TRENDING:
|
||||
videoCall = peertubeService.getTrendingVideos(getToken(), max_id, count, filter);
|
||||
videoCall = peertubeService.getTrendingVideos(getToken(), max_id, count, showNSFWVideos, filter);
|
||||
break;
|
||||
case HISTORY:
|
||||
videoCall = peertubeService.getHistory(getToken(), max_id, count, null, null);
|
||||
videoCall = peertubeService.getHistory(getToken(), max_id, count, showNSFWVideos, null, null);
|
||||
break;
|
||||
case RECENT:
|
||||
videoCall = peertubeService.getRecentlyAddedVideos(getToken(), max_id, count, filter);
|
||||
videoCall = peertubeService.getRecentlyAddedVideos(getToken(), max_id, count, showNSFWVideos, filter);
|
||||
break;
|
||||
}
|
||||
if (videoCall != null) {
|
||||
@ -462,7 +493,7 @@ public class RetrofitPeertubeAPI {
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
PeertubeService peertubeService = init();
|
||||
ArrayList<String> filter = selection != null ? new ArrayList<>(selection) : null;
|
||||
Call<OverviewVideo> overviewVideoCall = peertubeService.getOverviewVideos(getToken(), page, filter);
|
||||
Call<OverviewVideo> overviewVideoCall = peertubeService.getOverviewVideos(getToken(), page, showNSFWVideos, filter);
|
||||
try {
|
||||
Response<OverviewVideo> response = overviewVideoCall.execute();
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
@ -902,7 +933,7 @@ public class RetrofitPeertubeAPI {
|
||||
*/
|
||||
public APIResponse searchNextVideos(List<String> tags) {
|
||||
PeertubeService peertubeService = init();
|
||||
Call<VideoData> searchVideosCall = peertubeService.searchNextVideo(getToken(), tags, "0", "20");
|
||||
Call<VideoData> searchVideosCall = peertubeService.searchNextVideo(getToken(), tags, "0", "20", showNSFWVideos);
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
try {
|
||||
Response<VideoData> response = searchVideosCall.execute();
|
||||
@ -928,7 +959,7 @@ public class RetrofitPeertubeAPI {
|
||||
*/
|
||||
public APIResponse searchPeertube(String query, String max_id) {
|
||||
PeertubeService peertubeService = init();
|
||||
Call<VideoData> searchVideosCall = peertubeService.searchVideos(getToken(), query, max_id, count);
|
||||
Call<VideoData> searchVideosCall = peertubeService.searchVideos(getToken(), query, max_id, count, showNSFWVideos);
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
try {
|
||||
Response<VideoData> response = searchVideosCall.execute();
|
||||
|
@ -88,6 +88,8 @@ public class VideoData {
|
||||
private List<File> files;
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
@SerializedName("isLive")
|
||||
private boolean isLive = false;
|
||||
@SerializedName("isLocal")
|
||||
private boolean isLocal;
|
||||
@SerializedName("language")
|
||||
@ -163,6 +165,7 @@ public class VideoData {
|
||||
this.files = new ArrayList<>();
|
||||
in.readList(this.files, File.class.getClassLoader());
|
||||
this.id = in.readString();
|
||||
this.isLive = in.readByte() != 0;
|
||||
this.isLocal = in.readByte() != 0;
|
||||
this.language = in.readParcelable(ItemStr.class.getClassLoader());
|
||||
this.licence = in.readParcelable(Item.class.getClassLoader());
|
||||
@ -194,18 +197,9 @@ public class VideoData {
|
||||
public String getFileUrl(String resolution, Context context) {
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
int mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
|
||||
List<File> files = getAllFile(context);
|
||||
if (files != null && files.size() > 0) {
|
||||
return getFile(context, files, resolution, mode);
|
||||
} else if (streamingPlaylists != null && streamingPlaylists.size() > 0) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (StreamingPlaylists streamingPlaylists : streamingPlaylists) {
|
||||
if (streamingPlaylists.getFiles().size() > 0) {
|
||||
files.addAll(streamingPlaylists.getFiles());
|
||||
} else {
|
||||
return streamingPlaylists.getPlaylistUrl();
|
||||
}
|
||||
}
|
||||
return getFile(context, files, resolution, mode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -213,7 +207,7 @@ public class VideoData {
|
||||
public List<File> getAllFile(Context context) {
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
int mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
|
||||
if (files != null) {
|
||||
if (files != null && files.size() > 0) {
|
||||
return files;
|
||||
} else if (streamingPlaylists != null) {
|
||||
List<File> files = new ArrayList<>();
|
||||
@ -222,7 +216,7 @@ public class VideoData {
|
||||
}
|
||||
return files;
|
||||
}
|
||||
return null;
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
@ -413,6 +407,14 @@ public class VideoData {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean isLive() {
|
||||
return isLive;
|
||||
}
|
||||
|
||||
public void setLive(boolean live) {
|
||||
isLive = live;
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return isLocal;
|
||||
}
|
||||
@ -668,6 +670,7 @@ public class VideoData {
|
||||
dest.writeString(this.embedUrl);
|
||||
dest.writeList(this.files);
|
||||
dest.writeString(this.id);
|
||||
dest.writeByte(this.isLive ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(this.isLocal ? (byte) 1 : (byte) 0);
|
||||
dest.writeParcelable(this.language, flags);
|
||||
dest.writeParcelable(this.licence, flags);
|
||||
|
@ -23,7 +23,6 @@ import com.google.gson.annotations.SerializedName;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
public class VideoPlaylistData {
|
||||
|
||||
|
@ -38,7 +38,8 @@ public class OauthParams {
|
||||
private String refresh_token;
|
||||
@SerializedName("access_token")
|
||||
private String access_token;
|
||||
|
||||
@SerializedName("response_type")
|
||||
private String response_type;
|
||||
|
||||
public String getClient_secret() {
|
||||
return client_secret;
|
||||
@ -111,4 +112,12 @@ public class OauthParams {
|
||||
public void setAccess_token(String access_token) {
|
||||
this.access_token = access_token;
|
||||
}
|
||||
|
||||
public String getResponse_type() {
|
||||
return response_type;
|
||||
}
|
||||
|
||||
public void setResponse_type(String response_type) {
|
||||
this.response_type = response_type;
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,14 @@ import android.graphics.Color;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.fedilabtube.client.data.ChannelData;
|
||||
import app.fedilab.fedilabtube.databinding.DrawerHorizontalAccountBinding;
|
||||
import app.fedilab.fedilabtube.helper.Helper;
|
||||
|
@ -75,11 +75,11 @@ public class CommentListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
|
||||
private final List<Comment> comments;
|
||||
private final CommentListAdapter commentListAdapter;
|
||||
private final boolean isThread;
|
||||
private final String instance;
|
||||
private final boolean sepiaSearch;
|
||||
public AllCommentRemoved allCommentRemoved;
|
||||
boolean isVideoOwner;
|
||||
private Context context;
|
||||
private final String instance;
|
||||
private final boolean sepiaSearch;
|
||||
|
||||
public CommentListAdapter(List<Comment> comments, boolean isVideoOwner, boolean isThread, String instance, boolean sepiaSearch) {
|
||||
this.comments = comments;
|
||||
|
@ -55,6 +55,8 @@ import app.fedilab.fedilabtube.R;
|
||||
import app.fedilab.fedilabtube.ShowChannelActivity;
|
||||
import app.fedilab.fedilabtube.client.APIResponse;
|
||||
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
|
||||
import app.fedilab.fedilabtube.client.data.AccountData;
|
||||
import app.fedilab.fedilabtube.client.data.ChannelData;
|
||||
import app.fedilab.fedilabtube.client.data.PlaylistData;
|
||||
import app.fedilab.fedilabtube.client.data.VideoData;
|
||||
import app.fedilab.fedilabtube.client.entities.PlaylistExist;
|
||||
@ -82,12 +84,15 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||
private Context context;
|
||||
private TimelineVM.TimelineType timelineType;
|
||||
private boolean sepiaSearch;
|
||||
private ChannelData.Channel forChannel;
|
||||
private AccountData.Account forAccount;
|
||||
|
||||
|
||||
public PeertubeAdapter(List<VideoData.Video> videos, TimelineVM.TimelineType timelineType, boolean sepiaSearch) {
|
||||
public PeertubeAdapter(List<VideoData.Video> videos, TimelineVM.TimelineType timelineType, boolean sepiaSearch, ChannelData.Channel forChannel, AccountData.Account forAccount) {
|
||||
this.videos = videos;
|
||||
this.timelineType = timelineType;
|
||||
this.sepiaSearch = sepiaSearch || timelineType == SEPIA_SEARCH;
|
||||
this.forChannel = forChannel;
|
||||
this.forAccount = forAccount;
|
||||
}
|
||||
|
||||
|
||||
@ -127,16 +132,30 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||
ownVideos = Helper.isVideoOwner(context, video);
|
||||
}
|
||||
|
||||
|
||||
String instance = null;
|
||||
if (sepiaSearch) {
|
||||
instance = video.getAccount().getHost();
|
||||
} else if (forChannel != null) {
|
||||
instance = forChannel.getHost();
|
||||
} else if (forAccount != null) {
|
||||
instance = forAccount.getHost();
|
||||
}
|
||||
|
||||
|
||||
holder.binding.peertubeAccountName.setText(video.getChannel().getAcct());
|
||||
Helper.loadGiF(context, instance, video.getChannel().getAvatar() != null ? video.getChannel().getAvatar().getPath() : null, holder.binding.peertubeProfile);
|
||||
|
||||
holder.binding.peertubeTitle.setText(video.getName());
|
||||
holder.binding.peertubeDuration.setText(Helper.secondsToString(video.getDuration()));
|
||||
if (video.isLive()) {
|
||||
holder.binding.peertubeDuration.setText(R.string.live);
|
||||
holder.binding.peertubeDuration.setBackgroundResource(R.drawable.rounded_live);
|
||||
} else {
|
||||
holder.binding.peertubeDuration.setText(Helper.secondsToString(video.getDuration()));
|
||||
holder.binding.peertubeDuration.setBackgroundResource(R.drawable.rounded_corner);
|
||||
}
|
||||
|
||||
|
||||
holder.binding.peertubeDate.setText(String.format(" - %s", Helper.dateDiff(context, video.getCreatedAt())));
|
||||
holder.binding.peertubeViews.setText(context.getString(R.string.number_view_video, Helper.withSuffix(video.getViews())));
|
||||
|
||||
@ -172,8 +191,8 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||
Intent intent = new Intent(context, ShowChannelActivity.class);
|
||||
Bundle b = new Bundle();
|
||||
b.putParcelable("channel", video.getChannel());
|
||||
b.putBoolean("sepia_search", sepiaSearch);
|
||||
if (sepiaSearch) {
|
||||
b.putBoolean("sepia_search", sepiaSearch || forChannel != null);
|
||||
if (sepiaSearch || forChannel != null) {
|
||||
b.putString("peertube_instance", video.getAccount().getHost());
|
||||
}
|
||||
intent.putExtras(b);
|
||||
@ -389,14 +408,6 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||
}
|
||||
}
|
||||
|
||||
public interface RelationShipListener {
|
||||
Map<String, Boolean> getRelationShip();
|
||||
}
|
||||
|
||||
public interface PlaylistListener {
|
||||
Map<String, List<PlaylistExist>> getPlaylist();
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void loadImage(ImageView target, String instance, String urlPreview, String thumbnail, boolean blur) {
|
||||
if (urlPreview == null || urlPreview.startsWith("null")) {
|
||||
@ -459,6 +470,14 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||
|
||||
}
|
||||
|
||||
public interface RelationShipListener {
|
||||
Map<String, Boolean> getRelationShip();
|
||||
}
|
||||
|
||||
public interface PlaylistListener {
|
||||
Map<String, List<PlaylistExist>> getPlaylist();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
DrawerPeertubeBinding binding;
|
||||
|
||||
|
@ -33,7 +33,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
@ -68,8 +68,8 @@ import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQU
|
||||
|
||||
public class DisplayChannelsFragment extends Fragment implements ChannelListAdapter.AllChannelRemoved, ChannelListAdapter.EditAlertDialog {
|
||||
|
||||
private Context context;
|
||||
private static final int PICK_AVATAR = 467;
|
||||
private Context context;
|
||||
private ChannelListAdapter channelListAdapter;
|
||||
private List<ChannelData.Channel> channels;
|
||||
private String name;
|
||||
|
@ -30,7 +30,6 @@ 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;
|
||||
|
@ -96,7 +96,7 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
|
||||
binding.loader.setVisibility(View.VISIBLE);
|
||||
binding.loadingNextVideos.setVisibility(View.GONE);
|
||||
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true);
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true, null, null);
|
||||
binding.lvVideos.setAdapter(peertubeAdapater);
|
||||
|
||||
|
||||
@ -221,7 +221,7 @@ public class DisplaySepiaSearchFragment extends Fragment implements AccountsHori
|
||||
|
||||
//If no item were inserted previously the adapter is created
|
||||
if (previousPosition == 0) {
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true);
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, SEPIA_SEARCH, true, null, null);
|
||||
binding.lvVideos.setAdapter(peertubeAdapater);
|
||||
} else
|
||||
peertubeAdapater.notifyItemRangeInserted(previousPosition, videoData.data.size());
|
||||
|
@ -70,7 +70,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private GridLayoutManager gLayoutManager;
|
||||
private boolean flag_loading;
|
||||
private boolean flag_loading, flag_loading_account;
|
||||
private Context context;
|
||||
private PeertubeAdapter peertubeAdapater;
|
||||
private AccountsHorizontalListAdapter accountsHorizontalListAdapter;
|
||||
@ -127,6 +127,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
startDate = bundle.getString("startDate", null);
|
||||
endDate = bundle.getString("endDate", null);
|
||||
}
|
||||
|
||||
if (channel != null) {
|
||||
channelId = channel.getAcct();
|
||||
} else if (account != null) {
|
||||
@ -136,13 +137,14 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
//forChannel = type == TimelineVM.TimelineType.ACCOUNT_VIDEOS ? channelId : null;
|
||||
max_id_accounts = null;
|
||||
flag_loading = true;
|
||||
flag_loading_account = false;
|
||||
firstLoad = true;
|
||||
check_ScrollingUp = false;
|
||||
|
||||
binding.loader.setVisibility(View.VISIBLE);
|
||||
binding.loadingNextVideos.setVisibility(View.GONE);
|
||||
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch);
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch, forChannel, account);
|
||||
peertubeAdapater.playlistListener = this;
|
||||
peertubeAdapater.relationShipListener = this;
|
||||
binding.lvVideos.setAdapter(peertubeAdapater);
|
||||
@ -152,6 +154,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
= new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
|
||||
binding.lvAccounts.setLayoutManager(layoutManager);
|
||||
binding.lvAccounts.setAdapter(accountsHorizontalListAdapter);
|
||||
|
||||
if (!Helper.isTablet(context)) {
|
||||
mLayoutManager = new LinearLayoutManager(context);
|
||||
binding.lvVideos.setLayoutManager(mLayoutManager);
|
||||
@ -170,10 +173,11 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
binding.lvAccounts.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
|
||||
if (dy > 0) {
|
||||
if (dx > 0) {
|
||||
int visibleItemCount = layoutManager.getChildCount();
|
||||
int totalItemCount = layoutManager.getItemCount();
|
||||
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
|
||||
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null && !flag_loading_account) {
|
||||
flag_loading_account = true;
|
||||
viewModelAccounts.getAccounts(RetrofitPeertubeAPI.DataType.SUBSCRIBER, max_id_accounts).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageViewAccounts(apiResponse));
|
||||
}
|
||||
}
|
||||
@ -294,6 +298,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
|
||||
|
||||
private void manageViewAccounts(APIResponse apiResponse) {
|
||||
flag_loading_account = false;
|
||||
if (apiResponse != null && apiResponse.getChannels() != null && apiResponse.getChannels().size() > 0) {
|
||||
if (binding.topAccountContainer.getVisibility() == View.GONE) {
|
||||
binding.topAccountContainer.setVisibility(View.VISIBLE);
|
||||
@ -320,8 +325,13 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
if (this.peertubes == null || apiResponse == null || (apiResponse.getError() != null)) {
|
||||
if (apiResponse == null)
|
||||
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
else {
|
||||
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
|
||||
else if (apiResponse.getError() != null) {
|
||||
if (apiResponse.getError().getError().length() > 500) {
|
||||
Toasty.info(context, getString(R.string.remote_account), Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
}
|
||||
binding.swipeContainer.setRefreshing(false);
|
||||
flag_loading = false;
|
||||
@ -356,7 +366,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
|
||||
//If no item were inserted previously the adapter is created
|
||||
if (previousPosition == 0) {
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch);
|
||||
peertubeAdapater = new PeertubeAdapter(this.peertubes, type, sepiaSearch, forChannel, account);
|
||||
peertubeAdapater.playlistListener = DisplayVideosFragment.this;
|
||||
peertubeAdapater.relationShipListener = DisplayVideosFragment.this;
|
||||
binding.lvVideos.setAdapter(peertubeAdapater);
|
||||
@ -432,11 +442,9 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (binding.lvVideos != null) {
|
||||
try {
|
||||
binding.lvVideos.setAdapter(null);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
try {
|
||||
binding.lvVideos.setAdapter(null);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package app.fedilab.fedilabtube.helper;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.fedilabtube.client.data.CommentData;
|
||||
|
||||
public class CommentDecorationHelper {
|
||||
|
@ -80,7 +80,6 @@ import static android.content.Context.DOWNLOAD_SERVICE;
|
||||
|
||||
public class Helper {
|
||||
|
||||
public static PeertubeInformation peertubeInformation;
|
||||
public static final int RELOAD_MYVIDEOS = 10;
|
||||
public static final String SET_VIDEO_MODE = "set_video_mode";
|
||||
public static final String SET_QUALITY_MODE = "set_quality_mode";
|
||||
@ -132,8 +131,7 @@ public class Helper {
|
||||
public static final int VIDEOS_PER_PAGE = 10;
|
||||
public static final String RECEIVE_ACTION = "receive_action";
|
||||
public static final String SET_UNFOLLOW_VALIDATION = "set_unfollow_validation";
|
||||
|
||||
|
||||
public static PeertubeInformation peertubeInformation;
|
||||
|
||||
/**
|
||||
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
||||
|
@ -14,49 +14,25 @@ package app.fedilab.fedilabtube.helper;
|
||||
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class HelperAcadInstance {
|
||||
|
||||
|
||||
//List of available academies
|
||||
|
||||
public static String[] openid = {
|
||||
"ac-normandie.fr",
|
||||
"education.fr",
|
||||
"education.gouv.fr"
|
||||
//TODO: remove this one used for tests
|
||||
// "ac-orleans-tours.fr"
|
||||
};
|
||||
|
||||
public static String[] academies = {
|
||||
"ac-aix-marseille.fr",
|
||||
"ac-amiens.fr",
|
||||
"ac-besancon.fr",
|
||||
"ac-bordeaux.fr",
|
||||
"clermont-ferrand.fr",
|
||||
"ac-corse.fr",
|
||||
"ac-creteil.fr",
|
||||
"ac-dijon.fr",
|
||||
"ac-grenoble.fr",
|
||||
"education.fr",
|
||||
"ac-lille.fr",
|
||||
"ac-limoges.fr",
|
||||
"ac-lyon.fr",
|
||||
"ac-mayotte.fr",
|
||||
"ac-montpellier.fr",
|
||||
"ac-nancy.fr",
|
||||
"ac-nantes.fr",
|
||||
"ac-normandie.fr",
|
||||
"ac-orleans-tours.fr",
|
||||
"ac-paris.fr",
|
||||
"ac-poitiers.fr",
|
||||
"outremer.fr",
|
||||
"ac-rennes.fr",
|
||||
"ac-strasbourg.fr",
|
||||
"ac-toulouse.fr",
|
||||
"ac-versailles.fr"
|
||||
};
|
||||
public static Map<String, String> instances_themes;
|
||||
|
||||
public static String LOCAL = "LOCALES";
|
||||
public static String DISCOVER = "DECOUVRIR";
|
||||
public static String MOSTLIKED = "PLUS_APPRECIEES";
|
||||
public static String RECENTLY_ADDED = "AJOUTE_RECEMMENT";
|
||||
public static String TRENDING = "TENDANCE";
|
||||
public static String HISTORY = "HISTORIQUE";
|
||||
public static String SUBSCRIPTIONS = "ABONNEMENTS";
|
||||
public static String MYVIDEOS = "VIDEOS";
|
||||
|
||||
//List of available emails
|
||||
public static String[] valideEmails = {
|
||||
"ac-aix-marseille.fr",
|
||||
"ac-amiens.fr",
|
||||
@ -95,4 +71,20 @@ public class HelperAcadInstance {
|
||||
"igesr.gouv.fr"
|
||||
};
|
||||
|
||||
static {
|
||||
Map<String, String> is = new LinkedHashMap<>();
|
||||
is.put("Normandie", "tube-normandie.beta.education.fr");
|
||||
is.put("Enseignement professionnel", "tube-enseignement-professionnel.apps.education.fr");
|
||||
is.put("Action éducative", "tube-action-educative.apps.education.fr");
|
||||
is.put("Numérique éducatif", "tube-numerique-educatif.apps.education.fr");
|
||||
is.put("Institutionnel", "tube-institutionnelle.apps.education.fr");
|
||||
is.put("2d - langues vivantes", "tube-2d-langues-vivantes.apps.education.fr");
|
||||
is.put("2d - éducation physique et sportive", "tube-2d-education-physique-et-sportive.apps.education.fr");
|
||||
is.put("2d - arts, lettres et sciences humaines", "tube-2d-arts-lettres-sciences-humaines.apps.education.fr");
|
||||
is.put("Maternelle", "tube-maternelle.apps.education.fr");
|
||||
is.put("Cycle 2", "tube-cycle-2.apps.education.fr");
|
||||
is.put("Cycle 3", "tube-cycle-3.apps.education.fr");
|
||||
instances_themes = Collections.unmodifiableMap(is);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,40 +23,6 @@ import app.fedilab.fedilabtube.BuildConfig;
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
public class HelperInstance {
|
||||
|
||||
/**
|
||||
* Returns the peertube URL depending of the academic domain name
|
||||
*
|
||||
* @param acad String academic domain name
|
||||
* @return String the peertube URL
|
||||
*/
|
||||
public static String getPeertubeUrl(String acad) {
|
||||
|
||||
if (BuildConfig.full_instances) {
|
||||
return acad;
|
||||
}
|
||||
if (acad.compareTo("education.gouv.fr") == 0 || acad.compareTo("igesr.gouv.fr") == 0) {
|
||||
acad = "education.fr";
|
||||
} else if (acad.compareTo("ac-nancy-metz.fr") == 0) {
|
||||
acad = "ac-nancy.fr";
|
||||
} else if (acad.compareTo("clermont.fr") == 0) {
|
||||
acad = "clermont-ferrand.fr";
|
||||
} else if (acad.compareTo("ac-wf.wf") == 0 || acad.compareTo("ac-mayotte.fr") == 0 || acad.compareTo("ac-noumea.nc") == 0
|
||||
|| acad.compareTo("ac-guadeloupe.fr") == 0 || acad.compareTo("monvr.pf") == 0 || acad.compareTo("ac-reunion.fr") == 0 ||
|
||||
acad.compareTo("ac-martinique.fr") == 0 || acad.compareTo("ac-guyane.fr") == 0
|
||||
) {
|
||||
acad = "outremer.fr";
|
||||
}
|
||||
if (!acad.contains("ac-lyon.fr")) {
|
||||
//TODO: remove hack for test with openid
|
||||
/*if( acad.contains("orleans-tours.fr")) {
|
||||
return "tube-normandie.beta.education.fr";
|
||||
}*/
|
||||
return "tube-" + acad.replaceAll("ac-|\\.fr", "") + ".beta.education.fr";
|
||||
} else {
|
||||
return "tube.ac-lyon.fr";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the instance of the authenticated user
|
||||
@ -75,15 +41,11 @@ public class HelperInstance {
|
||||
} else if (BuildConfig.FLAVOR.compareTo("queermotion") == 0) {
|
||||
return sharedpreferences.getString(Helper.PREF_INSTANCE, "queermotion.org");
|
||||
} else {
|
||||
acad = sharedpreferences.getString(Helper.PREF_INSTANCE, "tube.ac-lyon.fr");
|
||||
acad = sharedpreferences.getString(Helper.PREF_INSTANCE, "tube-institutionnelle.apps.education.fr");
|
||||
if (acad == null) {
|
||||
acad = "tube.ac-lyon.fr";
|
||||
}
|
||||
if (acad.startsWith("tube-")) {
|
||||
return acad;
|
||||
} else {
|
||||
return getPeertubeUrl(acad);
|
||||
acad = "tube-institutionnelle.apps.education.fr";
|
||||
}
|
||||
return acad;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,12 @@ public class AccountsVM extends AndroidViewModel {
|
||||
Context _mContext = getApplication().getApplicationContext();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
RetrofitPeertubeAPI retrofitPeertubeAPI = new RetrofitPeertubeAPI(_mContext);
|
||||
RetrofitPeertubeAPI retrofitPeertubeAPI;
|
||||
if (acct.split("@").length > 1) {
|
||||
retrofitPeertubeAPI = new RetrofitPeertubeAPI(_mContext, acct.split("@")[1], null);
|
||||
} else {
|
||||
retrofitPeertubeAPI = new RetrofitPeertubeAPI(_mContext);
|
||||
}
|
||||
APIResponse apiResponse = retrofitPeertubeAPI.getAccount(acct);
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse);
|
||||
|
15
app/src/main/res/drawable/rounded_live.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/red_1" />
|
||||
|
||||
<solid android:color="@color/red_1" />
|
||||
|
||||
<padding
|
||||
android:bottom="1dp"
|
||||
android:left="1dp"
|
||||
android:right="1dp"
|
||||
android:top="1dp" />
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
@ -120,6 +120,36 @@
|
||||
android:importantForAutofill="no" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/instance_picker_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/instances_picker"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/instance_picker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/login_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/instance_picker_title" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="login_passwd_container,instance_picker" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/login_button"
|
||||
style="@style/Base.Widget.AppCompat.Button.Colored"
|
||||
@ -139,7 +169,7 @@
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_passwd_container" />
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
@ -112,21 +112,22 @@
|
||||
android:id="@+id/number_of_replies"
|
||||
app:layout_constraintTop_toBottomOf="@+id/comment_content"
|
||||
app:layout_constraintStart_toStartOf="@id/comment_account_profile"
|
||||
android:layout_marginEnd="15dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/replyButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/colorAccent"/>
|
||||
android:textColor="?attr/colorAccent" />
|
||||
|
||||
|
||||
<TextView
|
||||
app:layout_constraintTop_toBottomOf="@+id/comment_content"
|
||||
app:layout_constraintStart_toStartOf="@id/comment_account_profile"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginStart="10dp"
|
||||
app:layout_constraintStart_toEndOf="@id/number_of_replies"
|
||||
android:id="@+id/replyButton"
|
||||
app:layout_constraintTop_toTopOf="@+id/number_of_replies"
|
||||
android:text="@string/reply"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
||||
|
@ -103,6 +103,17 @@
|
||||
android:textColor="#FFBEBEBE"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exo_live_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/exo_fullscreen_button"
|
||||
android:layout_width="32dp"
|
||||
|
@ -350,4 +350,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Sprachfilter</string>
|
||||
<string name="set_video_language_description">Videos mit verschiedenen Sprachen filtern</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -345,4 +345,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Φίλτρο Γλώσσας</string>
|
||||
<string name="set_video_language_description">Φιλτράρετε βίντεο με διάφορες γλώσσες</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Filtro de idioma</string>
|
||||
<string name="set_video_language_description">Filtrar los videos con diferentes idiomas</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Filtre de langue</string>
|
||||
<string name="set_video_language_description">Filtrer les vidéos avec différentes langues</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Ridurre al minimo le dimensioni dei video quando l\'applicazione è in background (Android N+)</string>
|
||||
<string name="set_video_language">Filtro per le lingue</string>
|
||||
<string name="set_video_language_description">Filtra video con lingue diverse</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -345,4 +345,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -345,4 +345,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Minimaliseer de grootte van de video\'s als de app op de achtergrond staat (Android N+)</string>
|
||||
<string name="set_video_language">Taalfilter</string>
|
||||
<string name="set_video_language_description">Filtervideo\'s met verschillende talen</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -348,4 +348,7 @@
|
||||
<string name="set_video_minimize_description">Minimalizacja rozmiaru filmów, gdy aplikacja znajduje się w tle (Android N+)</string>
|
||||
<string name="set_video_language">Filtr językowy</string>
|
||||
<string name="set_video_language_description">Filtrowanie filmów w różnych językach</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -347,4 +347,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -348,4 +348,7 @@
|
||||
<string name="set_video_minimize_description">Уменьшить размер видео, когда приложение находится в фоновом режиме (Android N+)</string>
|
||||
<string name="set_video_language">Добавить языковой фильтр</string>
|
||||
<string name="set_video_language_description">Фильтровать видео с разными языками</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -346,4 +346,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -344,4 +344,7 @@
|
||||
<string name="set_video_minimize_description">当处于后台播放时,最小化视频(仅适用于 Android N 以及之后的版本)</string>
|
||||
<string name="set_video_language">语言筛选</string>
|
||||
<string name="set_video_language_description">筛选其他语言的视频</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -345,4 +345,7 @@
|
||||
<string name="set_video_minimize_description">Minimize videos size when the app is in background (Android N+)</string>
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
||||
|
@ -443,4 +443,7 @@
|
||||
|
||||
<string name="set_video_language">Language filter</string>
|
||||
<string name="set_video_language_description">Filter videos with different languages</string>
|
||||
<string name="live">Live</string>
|
||||
<string name="live_not_started">This live has not started!</string>
|
||||
<string name="remote_account">Account from another network!</string>
|
||||
</resources>
|
@ -6,15 +6,15 @@ files:
|
||||
two_letters_code:
|
||||
zh-TW: zh-rTW
|
||||
zh-CN: zh-rCN
|
||||
- source: /app/src/fdroid_full/fastlane/metadata/android/en-US/full_description.txt
|
||||
translation: /app/src/fdroid_full/fastlane/metadata/android/%two_letters_code%/%original_file_name%
|
||||
- source: /src/fdroid_full/fastlane/metadata/android/en-US/full_description.txt
|
||||
translation: /src/fdroid_full/fastlane/metadata/android/%two_letters_code%/%original_file_name%
|
||||
#update_option: update_without_changes
|
||||
languages_mapping:
|
||||
two_letters_code:
|
||||
zh-TW: zh-rTW
|
||||
zh-CN: zh-rCN
|
||||
- source: /app/src/fdroid_full/fastlane/metadata/android/en-US/short_description.txt
|
||||
translation: /app/src/fdroid_full/fastlane/metadata/android/%two_letters_code%/%original_file_name%
|
||||
- source: /src/fdroid_full/fastlane/metadata/android/en-US/short_description.txt
|
||||
translation: /src/fdroid_full/fastlane/metadata/android/%two_letters_code%/%original_file_name%
|
||||
#update_option: update_without_changes
|
||||
languages_mapping:
|
||||
two_letters_code:
|
||||
|
@ -0,0 +1,13 @@
|
||||
Fixes some issues on 1.10.0 (Crashes when adding a playlist + bad behavior when subscribing to remote accounts)
|
||||
|
||||
Added:
|
||||
- Chromecast support (default disabled)
|
||||
- Detect start time in URLs
|
||||
|
||||
Fixed:
|
||||
- Typo
|
||||
- Comment feature when logged out
|
||||
- Full-screen breaks
|
||||
- Crashes with the download button on live streams
|
||||
- Jumps with full-screen and vertical videos
|
||||
- Abuse report notifications clickable
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
@ -0,0 +1,16 @@
|
||||
Fixes some issues on 1.10.0 (Crashes when adding a playlist + bad behavior when subscribing to remote accounts)
|
||||
Added:
|
||||
- Chromecast support (default disabled)
|
||||
- Detect start time in URLs
|
||||
|
||||
Changed:
|
||||
- Instance picker supports URLs
|
||||
|
||||
Fixed:
|
||||
- Typo
|
||||
- Comment feature when logged out
|
||||
- Full-screen breaks
|
||||
- Crashes with the download button on live streams
|
||||
- Jumps with full-screen and vertical videos
|
||||
- Abuse report notifications clickable
|
||||
- Remote channel subscriptions need twice clicks
|
@ -0,0 +1,13 @@
|
||||
Added:
|
||||
- Live stream badge
|
||||
- Increment view count when watching a video
|
||||
|
||||
Changed:
|
||||
- Seek bar hidden with lives
|
||||
- Add a message if the live has not yet started
|
||||
|
||||
Fixed:
|
||||
- Do not list not honored when no accounts connected
|
||||
- Comments with replies show overlap
|
||||
- Mastodon accounts show errors
|
||||
- Accounts not found issue
|
@ -0,0 +1,13 @@
|
||||
Added:
|
||||
- Live stream badge
|
||||
- Increment view count when watching a video
|
||||
|
||||
Changed:
|
||||
- Seek bar hidden with lives
|
||||
- Add a message if the live has not yet started
|
||||
|
||||
Fixed:
|
||||
- Do not list not honored when no accounts connected
|
||||
- Comments with replies show overlap
|
||||
- Mastodon accounts show errors
|
||||
- Accounts not found issue
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 892 KiB After Width: | Height: | Size: 892 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |