diff --git a/app/build.gradle b/app/build.gradle
index fd59e47..cca1a94 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -3,13 +3,13 @@ apply plugin: 'com.android.application'
apply plugin: "androidx.navigation.safeargs"
android {
- compileSdkVersion 29
- buildToolsVersion "29.0.3"
+ compileSdkVersion 30
+ buildToolsVersion "30.0.2"
defaultConfig {
applicationId "app.fedilab.fedilabtube"
minSdkVersion 21
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 3
versionName "1.0.2"
multiDexEnabled true
@@ -41,8 +41,9 @@ dependencies {
implementation "androidx.multidex:multidex:2.0.1"
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.2.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation "androidx.fragment:fragment:1.2.5"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d7d6854..fcee910 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -49,8 +49,12 @@
android:name=".ShowAccountActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
- android:theme="@style/AppThemeNoActionBar"
android:windowSoftInputMode="stateAlwaysHidden" />
+
+
+
+
-
+
diff --git a/app/src/main/java/app/fedilab/fedilabtube/AccountActivity.java b/app/src/main/java/app/fedilab/fedilabtube/AccountActivity.java
new file mode 100644
index 0000000..b3c351d
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/AccountActivity.java
@@ -0,0 +1,256 @@
+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 . */
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.Bundle;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.UnderlineSpan;
+import android.view.MenuItem;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+
+import com.google.android.material.tabs.TabLayout;
+
+import org.jetbrains.annotations.NotNull;
+
+import app.fedilab.fedilabtube.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.fedilabtube.client.entities.Account;
+import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment;
+import app.fedilab.fedilabtube.fragment.DisplayNotificationsFragment;
+import app.fedilab.fedilabtube.helper.Helper;
+import app.fedilab.fedilabtube.sqlite.AccountDAO;
+import app.fedilab.fedilabtube.sqlite.Sqlite;
+
+
+public class AccountActivity extends AppCompatActivity {
+
+
+ private ViewPager mPager;
+ private TabLayout tabLayout;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+
+ setContentView(R.layout.activity_account);
+ if (getSupportActionBar() != null)
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+
+ SpannableString content_create = new SpannableString(getString(R.string.join_peertube));
+ content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0);
+ content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(AccountActivity.this, R.color.colorAccent)), 0, content_create.length(),
+ Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ String instance = Helper.getLiveInstance(AccountActivity.this);
+
+ TextView instanceView = findViewById(R.id.instance);
+ Account account = new AccountDAO(AccountActivity.this, db).getUniqAccount(userId, instance);
+ if (account == null) {
+ account = new AccountDAO(AccountActivity.this, db).getUniqAccount(userId, Helper.getPeertubeUrl(instance));
+ }
+
+
+ if (account == null) {
+ Helper.logoutCurrentUser(AccountActivity.this, null);
+ return;
+ }
+
+ ImageView profile_picture = findViewById(R.id.profile_picture);
+ TextView username = findViewById(R.id.username);
+ TextView displayname = findViewById(R.id.displayname);
+
+ setTitle(String.format("@%s", account.getUsername()));
+
+ Helper.loadGiF(AccountActivity.this, account, profile_picture);
+ username.setText(String.format("@%s", account.getUsername()));
+ displayname.setText(account.getDisplay_name());
+
+ instanceView.setText(account.getInstance());
+
+ Button logout_button = findViewById(R.id.logout_button);
+ Account finalAccount = account;
+ logout_button.setOnClickListener(v -> {
+ AlertDialog.Builder dialogBuilderLogoutAccount = new AlertDialog.Builder(AccountActivity.this);
+ dialogBuilderLogoutAccount.setMessage(getString(R.string.logout_account_confirmation, finalAccount.getUsername()));
+ dialogBuilderLogoutAccount.setPositiveButton(R.string.action_logout, (dialog, id) -> {
+ Helper.logoutCurrentUser(AccountActivity.this, finalAccount);
+ dialog.dismiss();
+ });
+ dialogBuilderLogoutAccount.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
+ AlertDialog alertDialogLogoutAccount = dialogBuilderLogoutAccount.create();
+ alertDialogLogoutAccount.show();
+ });
+
+ Button settings = findViewById(R.id.settings);
+ settings.setOnClickListener(v -> {
+ Intent intent = new Intent(AccountActivity.this, SettingsActivity.class);
+ startActivity(intent);
+ });
+
+ tabLayout = findViewById(R.id.account_tabLayout);
+ mPager = findViewById(R.id.account_viewpager);
+ tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.title_notifications)));
+ tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.title_muted)));
+ tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.title_channel)));
+
+
+ mPager.setOffscreenPageLimit(3);
+
+
+ mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ TabLayout.Tab tab = tabLayout.getTabAt(position);
+ if (tab != null)
+ tab.select();
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+
+ }
+ });
+
+
+ tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
+ @Override
+ public void onTabSelected(TabLayout.Tab tab) {
+ mPager.setCurrentItem(tab.getPosition());
+ }
+
+ @Override
+ public void onTabUnselected(TabLayout.Tab tab) {
+
+ }
+
+ @Override
+ public void onTabReselected(TabLayout.Tab tab) {
+ Fragment fragment = null;
+ if (mPager.getAdapter() != null)
+ fragment = (Fragment) mPager.getAdapter().instantiateItem(mPager, tab.getPosition());
+ switch (tab.getPosition()) {
+ case 0:
+ if (fragment != null) {
+ DisplayNotificationsFragment displayNotificationsFragment = ((DisplayNotificationsFragment) fragment);
+ displayNotificationsFragment.scrollToTop();
+ }
+ break;
+ case 1:
+ case 2:
+ if (fragment != null) {
+ DisplayAccountsFragment displayAccountsFragment = ((DisplayAccountsFragment) fragment);
+ displayAccountsFragment.scrollToTop();
+ }
+ break;
+ }
+ }
+ });
+
+ PagerAdapter mPagerAdapter = new AccountsPagerAdapter(getSupportFragmentManager());
+ mPager.setAdapter(mPagerAdapter);
+
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+
+ /**
+ * Pager adapter for three tabs (notifications, muted, blocked)
+ */
+ private class AccountsPagerAdapter extends FragmentStatePagerAdapter {
+
+ AccountsPagerAdapter(FragmentManager fm) {
+ super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
+ }
+
+ @NotNull
+ @Override
+ public Fragment getItem(int position) {
+ Bundle bundle = new Bundle();
+ switch (position) {
+ case 1:
+ case 2:
+ DisplayAccountsFragment displayAccountsFragment = new DisplayAccountsFragment();
+ if (position == 1) {
+ bundle.putSerializable("accountFetch", RetrieveAccountsAsyncTask.accountFetch.MUTED);
+ } else {
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ String instance = Helper.getLiveInstance(AccountActivity.this);
+ Account account = new AccountDAO(AccountActivity.this, db).getUniqAccount(userId, instance);
+ bundle.putString("name", account.getUsername() + "@" + account.getInstance());
+ bundle.putSerializable("accountFetch", RetrieveAccountsAsyncTask.accountFetch.CHANNEL);
+ }
+ displayAccountsFragment.setArguments(bundle);
+ return displayAccountsFragment;
+ default:
+ return new DisplayNotificationsFragment();
+ }
+ }
+
+
+ @Override
+ public int getCount() {
+ return 3;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java b/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java
index 7343f46..b397990 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java
@@ -104,9 +104,11 @@ public class AllPlaylistsActivity extends AppCompatActivity implements OnPlaylis
LinkedHashMap privaciesInit = new LinkedHashMap<>(peertubeInformation.getPrivacies());
- Map.Entry entryInt = privaciesInit.entrySet().iterator().next();
- privacyToSend = new HashMap<>();
- privacyToSend.put(entryInt.getKey(), entryInt.getValue());
+ if (privaciesInit.size() > 0) {
+ Map.Entry entryInt = privaciesInit.entrySet().iterator().next();
+ privacyToSend = new HashMap<>();
+ privacyToSend.put(entryInt.getKey(), entryInt.getValue());
+ }
add_new.setOnClickListener(view -> {
@@ -176,7 +178,6 @@ public class AllPlaylistsActivity extends AppCompatActivity implements OnPlaylis
public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
Exception exception) {
// your code here
- exception.printStackTrace();
}
@Override
diff --git a/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java b/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java
index aef8d5b..8a18d04 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java
@@ -16,7 +16,6 @@ package app.fedilab.fedilabtube;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.SpannableString;
@@ -24,51 +23,32 @@ import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.view.MenuItem;
-import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.textfield.TextInputLayout;
-import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
-import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeNotificationsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.UpdateAccountInfoAsyncTask;
-import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.HttpsConnection;
-import app.fedilab.fedilabtube.client.entities.Account;
-import app.fedilab.fedilabtube.client.entities.PeertubeNotification;
-import app.fedilab.fedilabtube.drawer.PeertubeNotificationsListAdapter;
import app.fedilab.fedilabtube.helper.Helper;
-import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeNotificationsInterface;
-import app.fedilab.fedilabtube.sqlite.AccountDAO;
-import app.fedilab.fedilabtube.sqlite.Sqlite;
import es.dmoral.toasty.Toasty;
-public class LoginActivity extends AppCompatActivity implements OnRetrievePeertubeNotificationsInterface {
+public class LoginActivity extends AppCompatActivity {
//Peertube notification type
@@ -82,23 +62,11 @@ public class LoginActivity extends AppCompatActivity implements OnRetrievePeertu
public static int MY_VIDEO_IMPORT_ERROR = 8;
private static String client_id;
private static String client_secret;
- // public static int NEW_USER_REGISTRATION = 9;
- //public static int NEW_FOLLOW = 10;
- // public static int COMMENT_MENTION = 11;
- LinearLayoutManager mLayoutManager;
private EditText login_uid;
private EditText login_passwd;
private Button connectionButton;
private String actionToken;
- private boolean flag_loading;
- private PeertubeNotificationsListAdapter notificationsListAdapter;
- private String max_id;
- private List notifications;
- private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
- private boolean firstLoad;
- private SwipeRefreshLayout swipeRefreshLayout;
- private boolean swiped;
- private AsyncTask asyncTask;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -153,99 +121,6 @@ public class LoginActivity extends AppCompatActivity implements OnRetrievePeertu
}
}
});
- LinearLayout connected = findViewById(R.id.connected);
- LinearLayout not_connected = findViewById(R.id.not_connected);
-
- if (Helper.isLoggedIn(LoginActivity.this)) {
- not_connected.setVisibility(View.GONE);
- connected.setVisibility(View.VISIBLE);
- SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
- SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- String instance = Helper.getLiveInstance(LoginActivity.this);
-
- TextView instanceView = findViewById(R.id.instance);
- Account account = new AccountDAO(LoginActivity.this, db).getUniqAccount(userId, instance);
- if (account == null) {
- account = new AccountDAO(LoginActivity.this, db).getUniqAccount(userId, Helper.getPeertubeUrl(instance));
- }
- if (account != null) {
- ImageView profile_picture = findViewById(R.id.profile_picture);
- TextView username = findViewById(R.id.username);
- TextView displayname = findViewById(R.id.displayname);
-
- Helper.loadGiF(LoginActivity.this, account, profile_picture);
- username.setText(String.format("@%s", account.getUsername()));
- displayname.setText(account.getDisplay_name());
-
- instanceView.setText(account.getInstance());
-
- Button logout_button = findViewById(R.id.logout_button);
- Account finalAccount = account;
- logout_button.setOnClickListener(v -> {
- AlertDialog.Builder dialogBuilderLogoutAccount = new AlertDialog.Builder(LoginActivity.this);
- dialogBuilderLogoutAccount.setMessage(getString(R.string.logout_account_confirmation, finalAccount.getUsername()));
- dialogBuilderLogoutAccount.setPositiveButton(R.string.action_logout, (dialog, id) -> {
- Helper.logoutCurrentUser(LoginActivity.this, finalAccount);
- dialog.dismiss();
- });
- dialogBuilderLogoutAccount.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
- AlertDialog alertDialogLogoutAccount = dialogBuilderLogoutAccount.create();
- alertDialogLogoutAccount.show();
- });
- } else {
- Helper.logoutCurrentUser(LoginActivity.this, null);
- }
-
- max_id = null;
- firstLoad = true;
- flag_loading = true;
- notifications = new ArrayList<>();
- swiped = false;
- swipeRefreshLayout = findViewById(R.id.swipeContainer);
-
- RecyclerView lv_notifications = findViewById(R.id.lv_notifications);
- mainLoader = findViewById(R.id.loader);
- nextElementLoader = findViewById(R.id.loading_next_notifications);
- textviewNoAction = findViewById(R.id.no_action);
- mainLoader.setVisibility(View.VISIBLE);
- nextElementLoader.setVisibility(View.GONE);
- notificationsListAdapter = new PeertubeNotificationsListAdapter(this.notifications);
- lv_notifications.setAdapter(notificationsListAdapter);
- mLayoutManager = new LinearLayoutManager(LoginActivity.this);
- lv_notifications.setLayoutManager(mLayoutManager);
- lv_notifications.addOnScrollListener(new RecyclerView.OnScrollListener() {
- public void onScrolled(@NotNull RecyclerView recyclerView, int dx, int dy) {
- if (dy > 0) {
- int visibleItemCount = mLayoutManager.getChildCount();
- int totalItemCount = mLayoutManager.getItemCount();
- int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
- if (firstVisibleItem + visibleItemCount == totalItemCount) {
- if (!flag_loading) {
- flag_loading = true;
- asyncTask = new RetrievePeertubeNotificationsAsyncTask(LoginActivity.this, null, max_id, LoginActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- nextElementLoader.setVisibility(View.VISIBLE);
- }
- } else {
- nextElementLoader.setVisibility(View.GONE);
- }
- }
- }
- });
-
-
- swipeRefreshLayout.setOnRefreshListener(() -> {
- max_id = null;
- firstLoad = true;
- flag_loading = true;
- swiped = true;
- asyncTask = new RetrievePeertubeNotificationsAsyncTask(LoginActivity.this, null, null, LoginActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- });
- asyncTask = new RetrievePeertubeNotificationsAsyncTask(LoginActivity.this, null, max_id, LoginActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- connected.setVisibility(View.GONE);
- not_connected.setVisibility(View.VISIBLE);
- }
connectionButton.setOnClickListener(v -> {
@@ -431,50 +306,7 @@ public class LoginActivity extends AppCompatActivity implements OnRetrievePeertu
@Override
public void onDestroy() {
super.onDestroy();
- if (asyncTask != null && !asyncTask.isCancelled()) {
- asyncTask.cancel(true);
- }
}
- @Override
- public void onRetrievePeertubeNotifications(APIResponse apiResponse, Account account) {
- mainLoader.setVisibility(View.GONE);
- nextElementLoader.setVisibility(View.GONE);
- if (apiResponse.getError() != null) {
- Toasty.error(LoginActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
- flag_loading = false;
- swipeRefreshLayout.setRefreshing(false);
- swiped = false;
- return;
- }
-
- int previousPosition = notifications.size();
- max_id = apiResponse.getMax_id();
- List notifications = apiResponse.getPeertubeNotifications();
- if (!swiped && firstLoad && (notifications == null || notifications.size() == 0))
- textviewNoAction.setVisibility(View.VISIBLE);
- else
- textviewNoAction.setVisibility(View.GONE);
- if (swiped) {
- if (previousPosition > 0) {
- this.notifications.subList(0, previousPosition).clear();
- notificationsListAdapter.notifyItemRangeRemoved(0, previousPosition);
- }
- swiped = false;
- }
-
- if (notifications != null && notifications.size() > 0) {
- this.notifications.addAll(notifications);
- notificationsListAdapter.notifyItemRangeInserted(previousPosition, notifications.size());
- } else {
- if (firstLoad)
- textviewNoAction.setVisibility(View.VISIBLE);
- }
- swipeRefreshLayout.setRefreshing(false);
- firstLoad = false;
- //The initial call comes from a classic tab refresh
- flag_loading = (max_id == null);
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
index 7908865..17ae74b 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
@@ -39,14 +39,18 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
import org.jetbrains.annotations.NotNull;
+import java.util.LinkedHashMap;
+
import app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyncTask;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
+import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
+import static app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyncTask.peertubeInformation;
import static app.fedilab.fedilabtube.helper.Helper.academies;
public class MainActivity extends AppCompatActivity {
@@ -64,6 +68,13 @@ public class MainActivity extends AppCompatActivity {
}
try {
+ peertubeInformation = new PeertubeInformation();
+ peertubeInformation.setCategories(new LinkedHashMap<>());
+ peertubeInformation.setLanguages(new LinkedHashMap<>());
+ peertubeInformation.setLicences(new LinkedHashMap<>());
+ peertubeInformation.setPrivacies(new LinkedHashMap<>());
+ peertubeInformation.setPlaylistPrivacies(new LinkedHashMap<>());
+ peertubeInformation.setTranslations(new LinkedHashMap<>());
new RetrievePeertubeInformationAsyncTask(MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} catch (Exception ignored) {
}
@@ -131,11 +142,13 @@ public class MainActivity extends AppCompatActivity {
MenuItem uploadItem = menu.findItem(R.id.action_upload);
MenuItem myVideosItem = menu.findItem(R.id.action_myvideos);
MenuItem playslistItem = menu.findItem(R.id.action_playlist);
+ MenuItem historyItem = menu.findItem(R.id.action_history);
if (Helper.isLoggedIn(MainActivity.this)) {
instanceItem.setVisible(false);
uploadItem.setVisible(true);
myVideosItem.setVisible(true);
playslistItem.setVisible(true);
+ historyItem.setVisible(true);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(MainActivity.this);
@@ -149,6 +162,7 @@ public class MainActivity extends AppCompatActivity {
uploadItem.setVisible(false);
myVideosItem.setVisible(false);
playslistItem.setVisible(false);
+ historyItem.setVisible(false);
}
return true;
}
@@ -159,7 +173,12 @@ public class MainActivity extends AppCompatActivity {
showRadioButtonDialog();
return true;
} else if (item.getItemId() == R.id.action_account) {
- Intent intent = new Intent(MainActivity.this, LoginActivity.class);
+ Intent intent;
+ if (Helper.isLoggedIn(MainActivity.this)) {
+ intent = new Intent(MainActivity.this, AccountActivity.class);
+ } else {
+ intent = new Intent(MainActivity.this, LoginActivity.class);
+ }
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.action_upload) {
@@ -173,6 +192,13 @@ public class MainActivity extends AppCompatActivity {
intent.putExtras(bundle);
startActivity(intent);
return true;
+ } else if (item.getItemId() == R.id.action_history) {
+ Intent intent = new Intent(MainActivity.this, MyVideosActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PEERTUBE_HISTORY);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ return true;
} else if (item.getItemId() == R.id.action_playlist) {
Intent intent = new Intent(MainActivity.this, AllPlaylistsActivity.class);
startActivity(intent);
diff --git a/app/src/main/java/app/fedilab/fedilabtube/MyVideosActivity.java b/app/src/main/java/app/fedilab/fedilabtube/MyVideosActivity.java
index eda9919..a0f12d9 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/MyVideosActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/MyVideosActivity.java
@@ -47,6 +47,8 @@ public class MyVideosActivity extends AppCompatActivity implements OnRetrieveFee
setTitle(R.string.my_videos);
} else if (type == RetrieveFeedsAsyncTask.Type.PSUBSCRIPTIONS) {
setTitle(R.string.subscriptions);
+ } else if (type == RetrieveFeedsAsyncTask.Type.PEERTUBE_HISTORY) {
+ setTitle(R.string.my_history);
}
if (savedInstanceState == null) {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
index c3deb1b..25e2c67 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
@@ -201,9 +201,9 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_DIRECT);
- if (mode != Helper.VIDEO_MODE_WEBVIEW && mode != Helper.VIDEO_MODE_DIRECT)
- mode = Helper.VIDEO_MODE_DIRECT;
+ mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
+ if (mode != Helper.VIDEO_MODE_WEBVIEW && mode != Helper.VIDEO_MODE_NORMAL)
+ mode = Helper.VIDEO_MODE_NORMAL;
if (mode == Helper.VIDEO_MODE_WEBVIEW) {
webview_video.setVisibility(View.VISIBLE);
playerView.setVisibility(View.GONE);
@@ -366,7 +366,7 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
loader.setVisibility(View.GONE);
return;
}
- if (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().get(0) == null || apiResponse.getPeertubes().get(0).getFileUrl(null, apiResponse.getPeertubes().get(0).isStreamService()) == null) {
+ if (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().get(0) == null || apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this) == null) {
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
loader.setVisibility(View.GONE);
return;
@@ -374,7 +374,6 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
peertube = apiResponse.getPeertubes().get(0);
//TODO: currently streaming service gives the wrong values for duration
- peertube.setStreamService(false);
new ManagePlaylistsAsyncTask(PeertubeActivity.this, GET_PLAYLIST_FOR_VIDEO, null, peertube.getId(), null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@@ -536,7 +535,7 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
e.printStackTrace();
}
- if (mode == Helper.VIDEO_MODE_DIRECT) {
+ if (mode == Helper.VIDEO_MODE_NORMAL) {
int video_cache = sharedpreferences.getInt(Helper.SET_VIDEO_CACHE, Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
@@ -544,11 +543,11 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this,
Util.getUserAgent(PeertubeActivity.this, null), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
- .createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, apiResponse.getPeertubes().get(0).isStreamService())));
+ .createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this)));
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this);
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
- .createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, apiResponse.getPeertubes().get(0).isStreamService())));
+ .createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, PeertubeActivity.this)));
}
player = ExoPlayerFactory.newSimpleInstance(PeertubeActivity.this);
@@ -564,10 +563,10 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
if (ContextCompat.checkSelfPermission(PeertubeActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(PeertubeActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PeertubeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
} else {
- Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, peertube.isStreamService()));
+ Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, PeertubeActivity.this));
}
} else {
- Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, peertube.isStreamService()));
+ Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, PeertubeActivity.this));
}
});
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
@@ -714,7 +713,7 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
resolution = controlView.findViewById(R.id.resolution);
resolution.setText(String.format("%sp", res));
- if (mode == Helper.VIDEO_MODE_DIRECT) {
+ if (mode == Helper.VIDEO_MODE_NORMAL) {
if (player != null)
player.release();
player = ExoPlayerFactory.newSimpleInstance(PeertubeActivity.this);
@@ -726,11 +725,11 @@ public class PeertubeActivity extends AppCompatActivity implements OnRetrievePee
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this,
Util.getUserAgent(PeertubeActivity.this, null), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
- .createMediaSource(Uri.parse(peertube.getFileUrl(res, peertube.isStreamService())));
+ .createMediaSource(Uri.parse(peertube.getFileUrl(res, PeertubeActivity.this)));
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this);
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
- .createMediaSource(Uri.parse(peertube.getFileUrl(res, peertube.isStreamService())));
+ .createMediaSource(Uri.parse(peertube.getFileUrl(res, PeertubeActivity.this)));
}
player.prepare(videoSource);
player.seekTo(0, position);
diff --git a/app/src/main/java/app/fedilab/fedilabtube/PeertubeEditUploadActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PeertubeEditUploadActivity.java
index f4b1e0e..def2414 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/PeertubeEditUploadActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/PeertubeEditUploadActivity.java
@@ -14,27 +14,47 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import com.bumptech.glide.Glide;
+
+import net.gotev.uploadservice.MultipartUploadRequest;
+import net.gotev.uploadservice.ServerResponse;
+import net.gotev.uploadservice.UploadInfo;
+import net.gotev.uploadservice.UploadNotificationConfig;
+import net.gotev.uploadservice.UploadStatusDelegate;
+
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import app.fedilab.fedilabtube.asynctasks.PostActionAsyncTask;
import app.fedilab.fedilabtube.asynctasks.PostPeertubeAsyncTask;
@@ -58,6 +78,8 @@ import static app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyn
public class PeertubeEditUploadActivity extends AppCompatActivity implements OnRetrievePeertubeInterface, OnPostActionInterface {
+ private final int PICK_IMAGE = 50378;
+ private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
HashMap categoryToSend;
HashMap licenseToSend;
HashMap privacyToSend;
@@ -71,6 +93,9 @@ public class PeertubeEditUploadActivity extends AppCompatActivity implements OnR
private LinkedHashMap channels;
private String videoId;
private Account channel;
+ private ImageView p_video_preview;
+ private Button set_preview;
+ private Peertube peertube;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -99,9 +124,10 @@ public class PeertubeEditUploadActivity extends AppCompatActivity implements OnR
p_video_title = findViewById(R.id.p_video_title);
p_video_description = findViewById(R.id.p_video_description);
p_video_tags = findViewById(R.id.p_video_tags);
+ p_video_preview = findViewById(R.id.p_video_preview);
set_upload_nsfw = findViewById(R.id.set_upload_nsfw);
set_upload_enable_comments = findViewById(R.id.set_upload_enable_comments);
-
+ set_preview = findViewById(R.id.set_preview);
set_upload_delete.setOnClickListener(v -> {
AlertDialog.Builder builderInner;
@@ -201,6 +227,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity implements OnR
channels = new LinkedHashMap<>();
+ setTitle(R.string.edit_video);
}
@@ -216,7 +243,7 @@ public class PeertubeEditUploadActivity extends AppCompatActivity implements OnR
}
//Peertube video
- Peertube peertube = apiResponse.getPeertubes().get(0);
+ peertube = apiResponse.getPeertubes().get(0);
if (peertube.isUpdate()) {
Toasty.success(PeertubeEditUploadActivity.this, getString(R.string.toast_peertube_video_updated), Toast.LENGTH_LONG).show();
@@ -231,6 +258,27 @@ public class PeertubeEditUploadActivity extends AppCompatActivity implements OnR
privacyToSend = peertube.getPrivacy();
categoryToSend = peertube.getCategory();
+ Glide.with(PeertubeEditUploadActivity.this)
+ .load("https://" + peertube.getInstance() + peertube.getThumbnailPath())
+ .into(p_video_preview);
+
+ set_preview.setOnClickListener(v -> {
+ if (ContextCompat.checkSelfPermission(PeertubeEditUploadActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
+ PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(PeertubeEditUploadActivity.this,
+ new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+ MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
+ return;
+ }
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("image/jpg");
+ String[] mimetypes = {"image/jpg", "image/jpeg"};
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
+ startActivityForResult(intent, PICK_IMAGE);
+
+ });
+
if (languageToSend == null) {
LinkedHashMap languages = new LinkedHashMap<>(peertubeInformation.getLanguages());
Map.Entry entryString = languages.entrySet().iterator().next();
@@ -498,6 +546,74 @@ public class PeertubeEditUploadActivity extends AppCompatActivity implements OnR
}
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
+ if (data == null || data.getData() == null) {
+ Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
+ return;
+ }
+ UploadNotificationConfig uploadConfig = new UploadNotificationConfig();
+ uploadConfig.getCompleted().autoClear = true;
+ try {
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
+ Uri uri = data.getData();
+ try {
+ String uploadId = UUID.randomUUID().toString();
+ new MultipartUploadRequest(PeertubeEditUploadActivity.this, uploadId, "https://" + Helper.getLiveInstance(PeertubeEditUploadActivity.this) + "/api/v1/" + String.format("/videos/%s", peertube.getId()))
+ .addFileToUpload(uri.toString().replace("file://", ""), "previewfile")
+ .setMethod("PUT")
+ .addHeader("Authorization", "Bearer " + token)
+ .setNotificationConfig(uploadConfig)
+ .setMaxRetries(2)
+ .setDelegate(new UploadStatusDelegate() {
+ @Override
+ public void onProgress(Context context, UploadInfo uploadInfo) {
+ // your code here
+ }
+
+ @Override
+ public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
+ Exception exception) {
+ Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
+ Glide.with(PeertubeEditUploadActivity.this)
+ .load(uri)
+ .into(p_video_preview);
+ }
+
+ @Override
+ public void onCancelled(Context context, UploadInfo uploadInfo) {
+ // your code here
+ }
+ })
+ .startUpload();
+ } catch (FileNotFoundException e) {
+ Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ e.printStackTrace();
+ }
+ } catch (MalformedURLException e) {
+ Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
@Override
public void onRetrievePeertubeComments(APIResponse apiResponse) {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/PeertubeUploadActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PeertubeUploadActivity.java
index 4ddb615..289da05 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/PeertubeUploadActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/PeertubeUploadActivity.java
@@ -15,7 +15,6 @@ package app.fedilab.fedilabtube;
* see . */
import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
@@ -42,15 +41,8 @@ import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import net.gotev.uploadservice.MultipartUploadRequest;
-import net.gotev.uploadservice.ServerResponse;
-import net.gotev.uploadservice.UploadInfo;
import net.gotev.uploadservice.UploadNotificationAction;
import net.gotev.uploadservice.UploadNotificationConfig;
-import net.gotev.uploadservice.UploadServiceSingleBroadcastReceiver;
-import net.gotev.uploadservice.UploadStatusDelegate;
-
-import org.json.JSONException;
-import org.json.JSONObject;
import java.io.File;
import java.util.Date;
@@ -71,7 +63,7 @@ import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.asynctasks.RetrievePeertubeInformationAsyncTask.peertubeInformation;
-public class PeertubeUploadActivity extends AppCompatActivity implements OnRetrievePeertubeInterface, UploadStatusDelegate {
+public class PeertubeUploadActivity extends AppCompatActivity implements OnRetrievePeertubeInterface {
private final int PICK_IVDEO = 52378;
@@ -85,7 +77,7 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
private String filename;
private HashMap privacyToSend;
private HashMap channelToSend;
- private UploadServiceSingleBroadcastReceiver uploadReceiver;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -105,10 +97,7 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
new RetrievePeertubeChannelsAsyncTask(PeertubeUploadActivity.this, PeertubeUploadActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
channels = new HashMap<>();
-
- uploadReceiver = new UploadServiceSingleBroadcastReceiver(this);
- uploadReceiver.register(this);
-
+ setTitle(R.string.upload_video);
}
@Override
@@ -122,6 +111,7 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
set_upload_submit.setEnabled(true);
uri = data.getData();
+
String uriString = uri.toString();
File myFile = new File(uriString);
filename = null;
@@ -151,7 +141,6 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
@Override
public void onDestroy() {
super.onDestroy();
- uploadReceiver.unregister(this);
}
@Override
@@ -327,7 +316,6 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
filename = video_title.getText().toString().trim();
}
String uploadId = UUID.randomUUID().toString();
- uploadReceiver.setUploadID(uploadId);
new MultipartUploadRequest(PeertubeUploadActivity.this, uploadId, "https://" + Helper.getLiveInstance(PeertubeUploadActivity.this) + "/api/v1/videos/upload")
.addFileToUpload(uri.toString().replace("file://", ""), "videofile")
.addHeader("Authorization", "Bearer " + token)
@@ -338,7 +326,7 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
.addParameter("nsfw", "false")
.addParameter("commentsEnabled", "true")
.addParameter("waitTranscoding", "true")
- .setMaxRetries(2)
+ .setMaxRetries(3)
.startUpload();
finish();
} catch (Exception exc) {
@@ -347,37 +335,4 @@ public class PeertubeUploadActivity extends AppCompatActivity implements OnRetri
}
});
}
-
-
- @Override
- public void onProgress(Context context, UploadInfo uploadInfo) {
- // your code here
- }
-
- @Override
- public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
- Exception exception) {
- // your code here
- exception.printStackTrace();
- }
-
- @SuppressLint("ApplySharedPref")
- @Override
- public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
- try {
- JSONObject response = new JSONObject(serverResponse.getBodyAsString());
- String videoID = response.getJSONObject("video").get("id").toString();
- SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.VIDEO_ID, videoID);
- editor.commit();
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onCancelled(Context context, UploadInfo uploadInfo) {
- // your code here
- }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/SettingsActivity.java b/app/src/main/java/app/fedilab/fedilabtube/SettingsActivity.java
new file mode 100644
index 0000000..529a4b0
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/SettingsActivity.java
@@ -0,0 +1,43 @@
+package app.fedilab.fedilabtube;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import app.fedilab.fedilabtube.fragment.SettingsFragment;
+
+/* 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 . */
+
+public class SettingsActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getSupportActionBar() != null)
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java b/app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java
index 6c23d23..41300e5 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java
@@ -23,16 +23,20 @@ import android.os.Bundle;
import android.text.Html;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -40,7 +44,6 @@ import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
-import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull;
@@ -49,9 +52,9 @@ import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.asynctasks.PostActionAsyncTask;
-import app.fedilab.fedilabtube.asynctasks.RetrieveAccountsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrieveRelationshipAsyncTask;
+import app.fedilab.fedilabtube.asynctasks.RetrieveSingleAccountAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
@@ -123,10 +126,8 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
statusDrawerParams.setStatuses(statuses);
statusListAdapter = new StatusListAdapter(statusDrawerParams);
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+
if (getSupportActionBar() != null) {
- getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_baseline_arrow_white_24);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@@ -135,18 +136,51 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
if (account != null) {
- ManageAccount();
- new RetrieveAccountsAsyncTask(ShowAccountActivity.this, account.getAcct(), RetrieveAccountsAsyncTask.actionType.CHANNEL, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ manageAccount();
+ new RetrieveSingleAccountAsyncTask(ShowAccountActivity.this, account.getAcct(), RetrieveSingleAccountAsyncTask.actionType.CHANNEL, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ new RetrieveSingleAccountAsyncTask(ShowAccountActivity.this, accountId, RetrieveSingleAccountAsyncTask.actionType.CHANNEL, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
@Override
- public boolean onSupportNavigateUp() {
- onBackPressed();
+ public boolean onCreateOptionsMenu(@NotNull Menu menu) {
+ getMenuInflater().inflate(R.menu.main_account, menu);
+ if (!Helper.isLoggedIn(ShowAccountActivity.this)) {
+ menu.findItem(R.id.action_mute).setVisible(false);
+ }
return true;
}
- private void ManageAccount() {
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ } else if (item.getItemId() == R.id.action_mute) {
+ new PostActionAsyncTask(ShowAccountActivity.this, PeertubeAPI.StatusAction.MUTE, account.getchannelOwner() != null ? account.getchannelOwner().getAcct() : account.getAcct(), ShowAccountActivity.this).execute();
+ } else if (item.getItemId() == R.id.action_report) {
+ androidx.appcompat.app.AlertDialog.Builder dialogBuilder = new androidx.appcompat.app.AlertDialog.Builder(ShowAccountActivity.this);
+ LayoutInflater inflater1 = getLayoutInflater();
+ View dialogView = inflater1.inflate(R.layout.popup_report, new LinearLayout(ShowAccountActivity.this), false);
+ dialogBuilder.setView(dialogView);
+ EditText report_content = dialogView.findViewById(R.id.report_content);
+ dialogBuilder.setNeutralButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
+ dialogBuilder.setPositiveButton(R.string.report, (dialog, id) -> {
+ if (report_content.getText().toString().trim().length() == 0) {
+ Toasty.info(ShowAccountActivity.this, getString(R.string.report_comment_size), Toasty.LENGTH_LONG).show();
+ } else {
+ new PostActionAsyncTask(ShowAccountActivity.this, PeertubeAPI.StatusAction.REPORT_ACCOUNT, account.getId(), report_content.getText().toString(), ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ dialog.dismiss();
+ }
+ });
+ androidx.appcompat.app.AlertDialog alertDialog = dialogBuilder.create();
+ alertDialog.show();
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void manageAccount() {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
String accountIdRelation = account.getAcct();
@@ -154,28 +188,9 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
retrieveRelationship = new RetrieveRelationshipAsyncTask(ShowAccountActivity.this, accountIdRelation, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
- TextView actionbar_title = findViewById(R.id.show_account_title);
- if (account.getAcct() != null)
- actionbar_title.setText(account.getAcct());
- ImageView pp_actionBar = findViewById(R.id.pp_actionBar);
- if (account.getAvatar() != null) {
- Helper.loadGiF(ShowAccountActivity.this, account, pp_actionBar);
-
- }
- final AppBarLayout appBar = findViewById(R.id.appBar);
+ setTitle(account.getAcct());
- appBar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
- if (pp_actionBar != null) {
- if (Math.abs(verticalOffset) - appBar.getTotalScrollRange() == 0) {
- if (pp_actionBar.getVisibility() == View.GONE)
- pp_actionBar.setVisibility(View.VISIBLE);
- } else {
- if (pp_actionBar.getVisibility() == View.VISIBLE)
- pp_actionBar.setVisibility(View.GONE);
- }
- }
- });
mPager = findViewById(R.id.account_viewpager);
if (!ischannel) {
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.videos)));
@@ -387,13 +402,24 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
Intent intentBC = new Intent(Helper.RECEIVE_ACTION);
intentBC.putExtras(b);
}
- retrieveRelationship = new RetrieveRelationshipAsyncTask(ShowAccountActivity.this, target, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if (statusAction == PeertubeAPI.StatusAction.UNFOLLOW || statusAction == PeertubeAPI.StatusAction.FOLLOW) {
+ retrieveRelationship = new RetrieveRelationshipAsyncTask(ShowAccountActivity.this, target, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else if (statusAction == PeertubeAPI.StatusAction.MUTE) {
+ Toasty.info(ShowAccountActivity.this, getString(R.string.muted_done), Toast.LENGTH_LONG).show();
+ }
}
@Override
public void onRetrieveAccounts(APIResponse apiResponse) {
if (apiResponse.getAccounts() != null && apiResponse.getAccounts().size() == 1) {
Account account = apiResponse.getAccounts().get(0);
+ if (this.account == null) {
+ this.account = account;
+ manageAccount();
+ }
+ if (account.getchannelOwner() != null) {
+ this.account.setchannelOwner(account.getchannelOwner());
+ }
subscriber_count.setText(getString(R.string.followers_count, Helper.withSuffix(account.getFollowers_count())));
subscriber_count.setVisibility(View.VISIBLE);
manageNotes(account);
@@ -424,7 +450,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
}
/**
- * Pager adapter for the 4 fragments
+ * Pager adapter for the 2 fragments
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/asynctasks/PostActionAsyncTask.java b/app/src/main/java/app/fedilab/fedilabtube/asynctasks/PostActionAsyncTask.java
index 3bccc88..294a718 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/asynctasks/PostActionAsyncTask.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/asynctasks/PostActionAsyncTask.java
@@ -65,9 +65,10 @@ public class PostActionAsyncTask extends AsyncTask {
protected Void doInBackground(Void... params) {
PeertubeAPI peertubeAPI = new PeertubeAPI(contextReference.get());
- if (apiAction == PeertubeAPI.StatusAction.FOLLOW || apiAction == PeertubeAPI.StatusAction.UNFOLLOW)
+ if (apiAction == PeertubeAPI.StatusAction.FOLLOW || apiAction == PeertubeAPI.StatusAction.UNFOLLOW
+ || apiAction == PeertubeAPI.StatusAction.MUTE || apiAction == PeertubeAPI.StatusAction.UNMUTE) {
statusCode = peertubeAPI.postAction(apiAction, targetedId);
- else if (apiAction == PeertubeAPI.StatusAction.RATEVIDEO)
+ } else if (apiAction == PeertubeAPI.StatusAction.RATEVIDEO)
statusCode = peertubeAPI.postRating(targetedId, comment);
else if (apiAction == PeertubeAPI.StatusAction.PEERTUBECOMMENT)
statusCode = peertubeAPI.postComment(targetedId, comment);
diff --git a/app/src/main/java/app/fedilab/fedilabtube/asynctasks/RetrieveAccountsAsyncTask.java b/app/src/main/java/app/fedilab/fedilabtube/asynctasks/RetrieveAccountsAsyncTask.java
index 4633c9b..2cb5303 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/asynctasks/RetrieveAccountsAsyncTask.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/asynctasks/RetrieveAccountsAsyncTask.java
@@ -28,12 +28,12 @@ public class RetrieveAccountsAsyncTask extends AsyncTask contextReference;
- private String name;
- private actionType type;
+ private String max_id;
+ private accountFetch type;
- public RetrieveAccountsAsyncTask(Context context, String name, actionType type, OnRetrieveAccountsInterface onRetrieveAccountsInterface) {
+ public RetrieveAccountsAsyncTask(Context context, String max_id, accountFetch type, OnRetrieveAccountsInterface onRetrieveAccountsInterface) {
this.contextReference = new WeakReference<>(context);
- this.name = name;
+ this.max_id = max_id;
this.listener = onRetrieveAccountsInterface;
this.type = type;
}
@@ -41,10 +41,12 @@ public class RetrieveAccountsAsyncTask extends AsyncTask {
+public class RetrievePeertubeNotificationsAsyncTask extends AsyncTask {
- private APIResponse apiResponse;
private String max_id;
private Account account;
private OnRetrievePeertubeNotificationsInterface listener;
@@ -44,24 +43,26 @@ public class RetrievePeertubeNotificationsAsyncTask extends AsyncTask. */
+
+import android.content.Context;
+import android.os.AsyncTask;
+
+import java.lang.ref.WeakReference;
+
+import app.fedilab.fedilabtube.client.APIResponse;
+import app.fedilab.fedilabtube.client.PeertubeAPI;
+import app.fedilab.fedilabtube.interfaces.OnRetrieveAccountsInterface;
+
+
+public class RetrieveSingleAccountAsyncTask extends AsyncTask {
+
+ private OnRetrieveAccountsInterface listener;
+ private WeakReference contextReference;
+ private String name;
+ private actionType type;
+
+ public RetrieveSingleAccountAsyncTask(Context context, String name, actionType type, OnRetrieveAccountsInterface onRetrieveAccountsInterface) {
+ this.contextReference = new WeakReference<>(context);
+ this.name = name;
+ this.listener = onRetrieveAccountsInterface;
+ this.type = type;
+ }
+
+ @Override
+ protected APIResponse doInBackground(Void... params) {
+ PeertubeAPI peertubeAPI = new PeertubeAPI(this.contextReference.get());
+ if (type == actionType.ACCOUNT) {
+ return peertubeAPI.getPeertubeChannel(name);
+ } else if (type == actionType.CHANNEL) {
+ return peertubeAPI.getPeertubeChannelInfo(name);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(APIResponse apiResponse) {
+ listener.onRetrieveAccounts(apiResponse);
+ }
+
+ public enum actionType {
+ ACCOUNT,
+ CHANNEL
+ }
+
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeAPI.java b/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeAPI.java
index 8360760..896e6d6 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeAPI.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeAPI.java
@@ -45,6 +45,7 @@ import java.util.Objects;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.AccountCreation;
+import app.fedilab.fedilabtube.client.entities.ChannelCreation;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.Instance;
import app.fedilab.fedilabtube.client.entities.Peertube;
@@ -167,6 +168,7 @@ public class PeertubeAPI {
peertubeAccountNotification.setDisplayName(channel.getString("displayName"));
peertubeAccountNotification.setName(channel.getString("name"));
peertubeAccountNotification.setId(channel.getString("id"));
+ peertubeAccountNotification.setHost(channel.getString("host"));
if (channel.has("avatar")) {
peertubeAccountNotification.setAvatar(channel.getJSONObject("avatar").getString("path"));
}
@@ -255,13 +257,11 @@ public class PeertubeAPI {
peertube.setCommentsEnabled(resobj.getBoolean("commentsEnabled"));
} catch (Exception ignored) {
}
-
try {
peertube.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt")));
} catch (ParseException e) {
e.printStackTrace();
}
-
try {
LinkedHashMap langue = new LinkedHashMap<>();
LinkedHashMap category = new LinkedHashMap<>();
@@ -271,7 +271,6 @@ public class PeertubeAPI {
license.put(resobj.getJSONObject("licence").getInt("id"), resobj.getJSONObject("licence").getString("label"));
privacy.put(resobj.getJSONObject("privacy").getInt("id"), resobj.getJSONObject("privacy").getString("label"));
langue.put(resobj.getJSONObject("language").getString("id"), resobj.getJSONObject("language").getString("label"));
-
peertube.setCategory(category);
peertube.setLicense(license);
peertube.setLanguage(langue);
@@ -345,7 +344,6 @@ public class PeertubeAPI {
resolutions.add(attObj.getJSONObject("resolution").getString("id"));
}
peertube.setResolution(resolutions);
- peertube.setStreamService(true);
} else {
JSONArray files = resobj.getJSONArray("files");
for (int j = 0; j < files.length(); j++) {
@@ -353,7 +351,6 @@ public class PeertubeAPI {
resolutions.add(attObj.getJSONObject("resolution").getString("id"));
}
peertube.setResolution(resolutions);
- peertube.setStreamService(false);
}
try {
LinkedHashMap langue = new LinkedHashMap<>();
@@ -433,6 +430,9 @@ public class PeertubeAPI {
account.setHost(accountObject.get("host").toString());
account.setSocial("PEERTUBE");
account.setInstance(accountObject.getString("host"));
+ if (accountObject.has("ownerAccount")) {
+ account.setchannelOwner(parseAccountResponsePeertube(accountObject.getJSONObject("ownerAccount")));
+ }
if (accountObject.has("createdAt"))
account.setCreated_at(Helper.mstStringToDate(accountObject.get("createdAt").toString()));
else
@@ -849,6 +849,45 @@ public class PeertubeAPI {
return apiResponse;
}
+ /**
+ * Create a channel fot the authenticated user
+ *
+ * @param channelCreation channelCreation
+ */
+ public void createChannel(ChannelCreation channelCreation) throws HttpsConnection.HttpsConnectionException {
+ actionCode = -1;
+ try {
+ HashMap params = new HashMap<>();
+ params.put("displayName", channelCreation.getDisplayName());
+ params.put("name", channelCreation.getName());
+ params.put("description", channelCreation.getDescription());
+ params.put("support", channelCreation.getSupport());
+ HttpsConnection httpsConnection = new HttpsConnection(context);
+ httpsConnection.post(getAbsoluteUrl("/video-channels"), 30, params, prefKeyOauthTokenT);
+ actionCode = httpsConnection.getActionCode();
+ } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Delete a Channel
+ *
+ * @param channelId String, the channel id
+ * @return int
+ */
+ public int deleteChannel(String channelId) throws HttpsConnection.HttpsConnectionException {
+ try {
+ HttpsConnection httpsConnection = new HttpsConnection(context);
+ httpsConnection.delete(getAbsoluteUrl(String.format("/video-channels/%s", channelId)), 60, null, prefKeyOauthTokenT);
+ actionCode = httpsConnection.getActionCode();
+ } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) {
+ e.printStackTrace();
+ }
+ return actionCode;
+ }
+
+
/***
* Verifiy credential of the authenticated user *synchronously*
* @return Account
@@ -1207,6 +1246,32 @@ public class PeertubeAPI {
return apiResponse;
}
+ /**
+ * Retrieves muted accounts *synchronously*
+ *
+ * @param max_id String id max
+ * @return APIResponse
+ */
+ public APIResponse getMuted(String max_id) {
+ List accounts = new ArrayList<>();
+ try {
+ HttpsConnection httpsConnection = new HttpsConnection(context);
+ HashMap params = new HashMap<>();
+ if (max_id != null)
+ params.put("start", max_id);
+ params.put("sort", "-createdAt");
+ String response = httpsConnection.get(getAbsoluteUrl("/users/me/blocklist/accounts"), 10, params, prefKeyOauthTokenT);
+ JSONArray jsonArray = new JSONObject(response).getJSONArray("data");
+ accounts = parseBlockedAccountResponsePeertube(jsonArray);
+ } catch (HttpsConnection.HttpsConnectionException e) {
+ setError(e.getStatusCode(), e);
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
+ e.printStackTrace();
+ }
+ apiResponse.setAccounts(accounts);
+ return apiResponse;
+ }
/**
* Retrieves overview videos *synchronously*
@@ -1525,6 +1590,15 @@ public class PeertubeAPI {
action = String.format("/users/me/subscriptions/%s", targetedId);
actionCall = "DELETE";
break;
+ case MUTE:
+ action = "/users/me/blocklist/accounts";
+ params = new HashMap<>();
+ params.put("accountName", targetedId);
+ break;
+ case UNMUTE:
+ action = String.format("/users/me/blocklist/accounts/%s", targetedId);
+ actionCall = "DELETE";
+ break;
case RATEVIDEO:
action = String.format("/videos/%s/rate", targetedId);
params = new HashMap<>();
@@ -1568,6 +1642,7 @@ public class PeertubeAPI {
actionCode = httpsConnection.getActionCode();
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
+ e.printStackTrace();
} catch (NoSuchAlgorithmException | IOException | KeyManagementException e) {
e.printStackTrace();
}
@@ -1632,6 +1707,29 @@ public class PeertubeAPI {
return apiResponse;
}
+
+ /**
+ * Create a Playlist
+ *
+ * @param playlistElement PlaylistElement, the playlist elements
+ * @return int
+ */
+ public int createPlaylist(PlaylistElement playlistElement) throws HttpsConnection.HttpsConnectionException {
+ try {
+ HttpsConnection httpsConnection = new HttpsConnection(context);
+ HashMap params = new HashMap<>();
+ params.put("videoChannelId", playlistElement.getVideoChannelId());
+ params.put("privacy", playlistElement.getPrivacy());
+ params.put("displayName", playlistElement.getDisplayName());
+ httpsConnection.post(getAbsoluteUrl("/video-playlists/"), 60, params, prefKeyOauthTokenT);
+ actionCode = httpsConnection.getActionCode();
+ } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) {
+ e.printStackTrace();
+ }
+ return actionCode;
+ }
+
+
/**
* Delete a Playlist
*
@@ -1898,6 +1996,25 @@ public class PeertubeAPI {
return playlists;
}
+
+ private List parseBlockedAccountResponsePeertube(JSONArray jsonArray) {
+ List accounts = new ArrayList<>();
+ try {
+ int i = 0;
+ while (i < jsonArray.length()) {
+ if (jsonArray.getJSONObject(i).has("blockedAccount")) {
+ JSONObject resobj = jsonArray.getJSONObject(i).getJSONObject("blockedAccount");
+ Account account = parseAccountResponsePeertube(resobj);
+ accounts.add(account);
+ }
+ i++;
+ }
+ } catch (JSONException e) {
+ setDefaultError(e);
+ }
+ return accounts;
+ }
+
private List parseAccountResponsePeertube(JSONArray jsonArray) {
List accounts = new ArrayList<>();
try {
@@ -1967,6 +2084,8 @@ public class PeertubeAPI {
public enum StatusAction {
FOLLOW,
UNFOLLOW,
+ MUTE,
+ UNMUTE,
RATEVIDEO,
PEERTUBECOMMENT,
PEERTUBEREPLY,
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/Account.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/Account.java
index da16d54..f60f444 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/entities/Account.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/Account.java
@@ -64,7 +64,7 @@ public class Account implements Parcelable {
private boolean isFollowing;
private followAction followType = followAction.NOTHING;
private boolean isMakingAction = false;
- private Account moved_to_account;
+ private Account channelOwner;
private boolean muting_notifications;
private String host;
private boolean isBot;
@@ -115,7 +115,7 @@ public class Account implements Parcelable {
int tmpFollowType = in.readInt();
this.followType = tmpFollowType == -1 ? null : followAction.values()[tmpFollowType];
this.isMakingAction = in.readByte() != 0;
- this.moved_to_account = in.readParcelable(Account.class.getClassLoader());
+ this.channelOwner = in.readParcelable(Account.class.getClassLoader());
this.muting_notifications = in.readByte() != 0;
this.host = in.readString();
this.isBot = in.readByte() != 0;
@@ -167,7 +167,7 @@ public class Account implements Parcelable {
dest.writeByte(this.isFollowing ? (byte) 1 : (byte) 0);
dest.writeInt(this.followType == null ? -1 : this.followType.ordinal());
dest.writeByte(this.isMakingAction ? (byte) 1 : (byte) 0);
- dest.writeParcelable(this.moved_to_account, flags);
+ dest.writeParcelable(this.channelOwner, flags);
dest.writeByte(this.muting_notifications ? (byte) 1 : (byte) 0);
dest.writeString(this.host);
dest.writeByte(this.isBot ? (byte) 1 : (byte) 0);
@@ -201,12 +201,12 @@ public class Account implements Parcelable {
isMakingAction = makingAction;
}
- public Account getMoved_to_account() {
- return moved_to_account;
+ public Account getchannelOwner() {
+ return channelOwner;
}
- public void setMoved_to_account(Account moved_to_account) {
- this.moved_to_account = moved_to_account;
+ public void setchannelOwner(Account moved_to_account) {
+ this.channelOwner = moved_to_account;
}
public boolean isMuting_notifications() {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/ChannelCreation.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/ChannelCreation.java
new file mode 100644
index 0000000..68b8cb6
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/ChannelCreation.java
@@ -0,0 +1,55 @@
+package app.fedilab.fedilabtube.client.entities;
+
+/* Copyright 2020 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+public class ChannelCreation {
+ private String displayName;
+ private String name;
+ private String description;
+ private String support;
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getSupport() {
+ return support;
+ }
+
+ public void setSupport(String support) {
+ this.support = support;
+ }
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/Peertube.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/Peertube.java
index 6a8dd87..545363c 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/entities/Peertube.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/Peertube.java
@@ -14,12 +14,17 @@ package app.fedilab.fedilabtube.client.entities;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.content.Context;
+import android.content.SharedPreferences;
+
import org.json.JSONObject;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import app.fedilab.fedilabtube.helper.Helper;
+
@SuppressWarnings("unused")
public class Peertube {
@@ -54,7 +59,6 @@ public class Peertube {
private String headerType = null;
private String headerTypeValue = null;
private JSONObject cache;
- private boolean streamService;
public Peertube() {
}
@@ -173,11 +177,13 @@ public class Peertube {
this.account = account;
}
- public String getFileUrl(String resolution, boolean streamService) {
+ public String getFileUrl(String resolution, Context context) {
if (resolution == null)
resolution = this.getResolution().get(0);
if (resolution == null)
return null;
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ boolean streamService = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL) == Helper.VIDEO_MODE_STREAMING;
if (streamService) {
return "https://" + this.host + "/static/streaming-playlists/hls/" + getUuid() + "/" + getUuid() + "-" + resolution + "-fragmented.mp4";
} else {
@@ -205,11 +211,13 @@ public class Peertube {
}
- public String getFileDownloadUrl(String resolution, boolean streamService) {
+ public String getFileDownloadUrl(String resolution, Context context) {
if (resolution == null)
resolution = this.getResolution().get(0);
if (resolution == null)
return null;
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ boolean streamService = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL) == Helper.VIDEO_MODE_STREAMING;
if (streamService) {
return "https://" + this.host + "/download/streaming-playlists/hls/videos/" + getUuid() + "/" + getUuid() + "-" + resolution + "-fragmented.mp4";
} else {
@@ -347,12 +355,4 @@ public class Peertube {
public void setHeaderTypeValue(String headerTypeValue) {
this.headerTypeValue = headerTypeValue;
}
-
- public boolean isStreamService() {
- return streamService;
- }
-
- public void setStreamService(boolean streamService) {
- this.streamService = streamService;
- }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/PlaylistElement.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/PlaylistElement.java
index 5e71d0e..a3f2044 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/entities/PlaylistElement.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/PlaylistElement.java
@@ -19,6 +19,10 @@ public class PlaylistElement {
private String playlistElementId;
private String playlistId;
+ private String videoChannelId;
+ private String privacy;
+ private String displayName;
+ private String description;
private long startTimestamp;
private long stopTimestamp;
@@ -53,4 +57,36 @@ public class PlaylistElement {
public void setStopTimestamp(long stopTimestamp) {
this.stopTimestamp = stopTimestamp;
}
+
+ public String getVideoChannelId() {
+ return videoChannelId;
+ }
+
+ public void setVideoChannelId(String videoChannelId) {
+ this.videoChannelId = videoChannelId;
+ }
+
+ public String getPrivacy() {
+ return privacy;
+ }
+
+ public void setPrivacy(String privacy) {
+ this.privacy = privacy;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java
index 0259b6a..5bf92c7 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java
@@ -14,10 +14,13 @@ package app.fedilab.fedilabtube.drawer;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.text.Html;
import android.text.util.Linkify;
import android.view.LayoutInflater;
@@ -29,6 +32,8 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -37,9 +42,13 @@ import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.ShowAccountActivity;
+import app.fedilab.fedilabtube.asynctasks.PostActionAsyncTask;
+import app.fedilab.fedilabtube.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.fedilabtube.client.HttpsConnection;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Error;
+import app.fedilab.fedilabtube.fragment.DisplayPlaylistsFragment;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnPostActionInterface;
import es.dmoral.toasty.Toasty;
@@ -47,17 +56,18 @@ import es.dmoral.toasty.Toasty;
public class AccountsListAdapter extends RecyclerView.Adapter implements OnPostActionInterface {
+ public AllAccountsRemoved allAccountsRemoved;
private List accounts;
-
private Context context;
private AccountsListAdapter accountsListAdapter;
+ private RetrieveAccountsAsyncTask.accountFetch type;
- public AccountsListAdapter(String targetedId, List accounts) {
+ public AccountsListAdapter(RetrieveAccountsAsyncTask.accountFetch type, List accounts) {
this.accounts = accounts;
this.accountsListAdapter = this;
+ this.type = type;
}
-
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@@ -70,10 +80,58 @@ public class AccountsListAdapter extends RecyclerView.Adapter {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(context.getString(R.string.action_channel_delete) + ": " + account.getAcct());
+ builder.setMessage(context.getString(R.string.action_channel_confirm_delete));
+ builder.setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(R.string.yes, (dialog, which) -> {
+ accounts.remove(account);
+ notifyDataSetChanged();
+ new Thread(() -> {
+ try {
+ new PeertubeAPI(context).deleteChannel(account.getAcct());
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ DisplayPlaylistsFragment displayPlaylistsFragment;
+ if (context == null)
+ return;
+ displayPlaylistsFragment = (DisplayPlaylistsFragment) ((AppCompatActivity) context).getSupportFragmentManager().findFragmentByTag("CHANNELS");
+ final FragmentTransaction ft = ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction();
+ if (displayPlaylistsFragment != null) {
+ ft.detach(displayPlaylistsFragment);
+ ft.attach(displayPlaylistsFragment);
+ ft.commit();
+ }
+ };
+ mainHandler.post(myRunnable);
+ } catch (HttpsConnection.HttpsConnectionException e) {
+ e.printStackTrace();
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ if (e.getMessage() != null) {
+ Toasty.error(context, e.getMessage(), Toast.LENGTH_LONG).show();
+ } else {
+ Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ }
+ };
+ mainHandler.post(myRunnable);
+ }
+ }).start();
+ dialog.dismiss();
+ })
+ .setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
+ .show();
+ });
+ } else if (type == RetrieveAccountsAsyncTask.accountFetch.MUTED) {
+ holder.account_action.setOnClickListener(v -> new PostActionAsyncTask(context, PeertubeAPI.StatusAction.UNMUTE, account.getAcct(), AccountsListAdapter.this).execute());
+ } else {
+ holder.account_action.hide();
+ }
if (account.getDisplay_name() != null && !account.getDisplay_name().trim().equals(""))
holder.account_dn.setText(account.getDisplay_name());
@@ -96,15 +154,16 @@ public class AccountsListAdapter extends RecyclerView.Adapter {
+ if (type == RetrieveAccountsAsyncTask.accountFetch.MUTED) {
+ holder.account_action.show();
+ holder.account_action.setImageResource(R.drawable.ic_baseline_volume_mute_24);
+ }
- });
holder.account_pp.setOnClickListener(v -> {
Intent intent = new Intent(context, ShowAccountActivity.class);
@@ -117,6 +176,7 @@ public class AccountsListAdapter extends RecyclerView.Adapter position)
- return accounts.get(position);
- else
- return null;
- }
-
@Override
public void onPostAction(int statusCode, PeertubeAPI.StatusAction statusAction, String targetedId, Error error) {
if (error != null) {
@@ -144,18 +197,28 @@ public class AccountsListAdapter extends RecyclerView.Adapter {
Intent intent = new Intent(context, ShowAccountActivity.class);
Bundle b = new Bundle();
- b.putBoolean("peertubeaccount", true);
- b.putString("accountId", finalAccountAction1.getName());
+ b.putString("accountId", finalAccountAction1.getName() + "@" + finalAccountAction1.getHost());
+ b.putBoolean("ischannel", true);
intent.putExtras(b);
context.startActivity(intent);
});
} else if (notification.getPeertubeComment() != null) { //Comment Notification
- String profileUrl = "https://" + Helper.getLiveInstance(context) + notification.getPeertubeComment().getPeertubeAccountNotification().getAvatar();
+ String profileUrl = notification.getPeertubeComment().getPeertubeAccountNotification().getAvatar();
Helper.loadGiF(context, profileUrl, holder.peertube_notif_pp);
accountAction = notification.getPeertubeComment().getPeertubeAccountNotification();
videoAction = notification.getPeertubeComment().getPeertubeVideoNotification();
@@ -113,7 +113,7 @@ public class PeertubeNotificationsListAdapter extends RecyclerView.Adapter {
Intent intent = new Intent(context, PlaylistsActivity.class);
@@ -101,7 +96,8 @@ public class PlaylistAdapter extends BaseAdapter implements OnPlaylistActionInte
context.startActivity(intent);
});
- holder.search_container.setOnLongClickListener(v -> {
+
+ holder.action_delete.setOnClickListener(v -> {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.action_lists_delete) + ": " + playlist.getDisplayName());
builder.setMessage(context.getString(R.string.action_lists_confirm_delete));
@@ -116,8 +112,6 @@ public class PlaylistAdapter extends BaseAdapter implements OnPlaylistActionInte
})
.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
.show();
-
- return false;
});
return convertView;
}
@@ -130,6 +124,7 @@ public class PlaylistAdapter extends BaseAdapter implements OnPlaylistActionInte
private static class ViewHolder {
LinearLayout search_container;
TextView search_title;
+ FloatingActionButton action_delete;
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayAccountsFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayAccountsFragment.java
index 1364ad4..bd0875e 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayAccountsFragment.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayAccountsFragment.java
@@ -14,35 +14,51 @@ package app.fedilab.fedilabtube.fragment;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
import android.widget.RelativeLayout;
+import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.fedilabtube.asynctasks.RetrieveSingleAccountAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
+import app.fedilab.fedilabtube.client.HttpsConnection;
+import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
+import app.fedilab.fedilabtube.client.entities.ChannelCreation;
import app.fedilab.fedilabtube.drawer.AccountsListAdapter;
import app.fedilab.fedilabtube.interfaces.OnRetrieveAccountsInterface;
import es.dmoral.toasty.Toasty;
-public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccountsInterface {
+public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccountsInterface, AccountsListAdapter.AllAccountsRemoved {
private boolean flag_loading;
private Context context;
@@ -53,24 +69,25 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout;
- private String targetedId, name;
+ private String name;
private boolean swiped;
private RecyclerView lv_accounts;
private View rootView;
+ private RetrieveAccountsAsyncTask.accountFetch accountFetch;
+ private FloatingActionButton action_button;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- rootView = inflater.inflate(R.layout.fragment_accounts, container, false);
+ rootView = inflater.inflate(R.layout.fragment_recyclerview, container, false);
context = getContext();
Bundle bundle = this.getArguments();
accounts = new ArrayList<>();
if (bundle != null) {
- if (bundle.containsKey("tag"))
- targetedId = bundle.getString("tag", null);
- else
- targetedId = bundle.getString("targetedid", null);
+ if (bundle.containsKey("accountFetch")) {
+ accountFetch = (RetrieveAccountsAsyncTask.accountFetch) bundle.getSerializable("accountFetch");
+ }
name = bundle.getString("name", null);
}
max_id = null;
@@ -81,16 +98,95 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
- lv_accounts = rootView.findViewById(R.id.lv_accounts);
+ if (getActivity() != null) {
+ action_button = getActivity().findViewById(R.id.action_button);
+ action_button.setOnClickListener(view -> {
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
+ LayoutInflater inflater1 = ((Activity) context).getLayoutInflater();
+ View dialogView = inflater1.inflate(R.layout.add_channel, new LinearLayout(context), false);
+ dialogBuilder.setView(dialogView);
+ EditText display_name = dialogView.findViewById(R.id.display_name);
+ EditText name = dialogView.findViewById(R.id.name);
+ EditText description = dialogView.findViewById(R.id.description);
+ dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
+ if (display_name.getText() != null && display_name.getText().toString().trim().length() > 0 && name.getText() != null && name.getText().toString().trim().length() > 0) {
+
+ ChannelCreation channelCreation = new ChannelCreation();
+ channelCreation.setDisplayName(display_name.getText().toString().trim());
+ channelCreation.setName(name.getText().toString().trim());
+ if (description.getText() != null && description.getText().toString().trim().length() > 0) {
+ channelCreation.setDescription(description.getText().toString().trim());
+ }
+ new Thread(() -> {
+ try {
+ new PeertubeAPI(context).createChannel(channelCreation);
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ DisplayPlaylistsFragment displayPlaylistsFragment;
+ if (getActivity() == null)
+ return;
+ displayPlaylistsFragment = (DisplayPlaylistsFragment) getActivity().getSupportFragmentManager().findFragmentByTag("CHANNELS");
+ final FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
+ if (displayPlaylistsFragment != null) {
+ ft.detach(displayPlaylistsFragment);
+ ft.attach(displayPlaylistsFragment);
+ ft.commit();
+ }
+ action_button.setEnabled(true);
+ };
+ mainHandler.post(myRunnable);
+ } catch (HttpsConnection.HttpsConnectionException e) {
+ action_button.setEnabled(true);
+ e.printStackTrace();
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ if (e.getMessage() != null) {
+ Toasty.error(context, e.getMessage(), Toast.LENGTH_LONG).show();
+ } else {
+ Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ }
+ };
+ mainHandler.post(myRunnable);
+ }
+ }).start();
+
+ dialog.dismiss();
+ action_button.setEnabled(false);
+ } else {
+ Toasty.error(context, context.getString(R.string.error_display_name_channel), Toast.LENGTH_LONG).show();
+ }
+
+ });
+ dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
+
+
+ AlertDialog alertDialog = dialogBuilder.create();
+ alertDialog.setTitle(getString(R.string.action_channel_create));
+ alertDialog.setOnDismissListener(dialogInterface -> {
+ //Hide keyboard
+ InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ assert imm != null;
+ imm.hideSoftInputFromWindow(display_name.getWindowToken(), 0);
+ });
+ if (alertDialog.getWindow() != null)
+ alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ alertDialog.show();
+ });
+ }
+ lv_accounts = rootView.findViewById(R.id.lv_elements);
lv_accounts.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
mainLoader = rootView.findViewById(R.id.loader);
- nextElementLoader = rootView.findViewById(R.id.loading_next_accounts);
+ nextElementLoader = rootView.findViewById(R.id.loading_next);
textviewNoAction = rootView.findViewById(R.id.no_action);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
- accountsListAdapter = new AccountsListAdapter(targetedId, this.accounts);
+ accountsListAdapter = new AccountsListAdapter(accountFetch, this.accounts);
+ accountsListAdapter.allAccountsRemoved = this;
lv_accounts.setAdapter(accountsListAdapter);
-
+ TextView no_action_text = rootView.findViewById(R.id.no_action_text);
+ if (accountFetch == RetrieveAccountsAsyncTask.accountFetch.MUTED) {
+ no_action_text.setText(context.getString(R.string.no_muted));
+ }
final LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(context);
lv_accounts.setLayoutManager(mLayoutManager);
@@ -103,7 +199,12 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
if (firstVisibleItem + visibleItemCount == totalItemCount) {
if (!flag_loading) {
flag_loading = true;
- asyncTask = new RetrieveAccountsAsyncTask(context, name, RetrieveAccountsAsyncTask.actionType.ACCOUNT, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if (accountFetch == null) {
+ asyncTask = new RetrieveSingleAccountAsyncTask(context, name, RetrieveSingleAccountAsyncTask.actionType.ACCOUNT, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ String param = accountFetch == RetrieveAccountsAsyncTask.accountFetch.CHANNEL ? name : max_id;
+ asyncTask = new RetrieveAccountsAsyncTask(context, param, accountFetch, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
nextElementLoader.setVisibility(View.VISIBLE);
}
} else {
@@ -114,10 +215,25 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
});
swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh);
- asyncTask = new RetrieveAccountsAsyncTask(context, name, RetrieveAccountsAsyncTask.actionType.ACCOUNT, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if (accountFetch == null) {
+ asyncTask = new RetrieveSingleAccountAsyncTask(context, name, RetrieveSingleAccountAsyncTask.actionType.ACCOUNT, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ String param = accountFetch == RetrieveAccountsAsyncTask.accountFetch.CHANNEL ? name : null;
+ asyncTask = new RetrieveAccountsAsyncTask(context, param, accountFetch, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
return rootView;
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (accountFetch == RetrieveAccountsAsyncTask.accountFetch.CHANNEL) {
+ action_button.setVisibility(View.VISIBLE);
+ } else {
+ action_button.setVisibility(View.GONE);
+ }
+ }
+
@Override
public void onDestroyView() {
super.onDestroyView();
@@ -169,7 +285,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
max_id = apiResponse.getMax_id();
if (swiped) {
- accountsListAdapter = new AccountsListAdapter(targetedId, this.accounts);
+ accountsListAdapter = new AccountsListAdapter(accountFetch, this.accounts);
lv_accounts.setAdapter(accountsListAdapter);
swiped = false;
}
@@ -189,7 +305,16 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
flag_loading = true;
swiped = true;
swipeRefreshLayout.setRefreshing(true);
- asyncTask = new RetrieveAccountsAsyncTask(context, name, RetrieveAccountsAsyncTask.actionType.ACCOUNT, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if (accountFetch == null) {
+ asyncTask = new RetrieveSingleAccountAsyncTask(context, name, RetrieveSingleAccountAsyncTask.actionType.ACCOUNT, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ String param = accountFetch == RetrieveAccountsAsyncTask.accountFetch.CHANNEL ? name : null;
+ asyncTask = new RetrieveAccountsAsyncTask(context, param, accountFetch, DisplayAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
}
+ @Override
+ public void onAllAccountsRemoved() {
+ textviewNoAction.setVisibility(View.VISIBLE);
+ }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayNotificationsFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayNotificationsFragment.java
new file mode 100644
index 0000000..14dab02
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayNotificationsFragment.java
@@ -0,0 +1,192 @@
+package app.fedilab.fedilabtube.fragment;
+/* 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 . */
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import app.fedilab.fedilabtube.R;
+import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeNotificationsAsyncTask;
+import app.fedilab.fedilabtube.client.APIResponse;
+import app.fedilab.fedilabtube.client.entities.Account;
+import app.fedilab.fedilabtube.client.entities.PeertubeNotification;
+import app.fedilab.fedilabtube.drawer.PeertubeNotificationsListAdapter;
+import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeNotificationsInterface;
+import es.dmoral.toasty.Toasty;
+
+
+public class DisplayNotificationsFragment extends Fragment implements OnRetrievePeertubeNotificationsInterface {
+
+ private boolean flag_loading;
+ private Context context;
+ private AsyncTask asyncTask;
+ private PeertubeNotificationsListAdapter peertubeNotificationsListAdapter;
+ private String max_id;
+ private List notifications;
+ private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
+ private boolean firstLoad;
+ private SwipeRefreshLayout swipeRefreshLayout;
+ private boolean swiped;
+ private RecyclerView lv_notifications;
+ private View rootView;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ rootView = inflater.inflate(R.layout.fragment_recyclerview, container, false);
+
+ context = getContext();
+ notifications = new ArrayList<>();
+ max_id = null;
+ firstLoad = true;
+ flag_loading = true;
+ swiped = false;
+
+ swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
+
+
+ lv_notifications = rootView.findViewById(R.id.lv_elements);
+ lv_notifications.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
+ mainLoader = rootView.findViewById(R.id.loader);
+ nextElementLoader = rootView.findViewById(R.id.loading_next);
+ textviewNoAction = rootView.findViewById(R.id.no_action);
+ mainLoader.setVisibility(View.VISIBLE);
+ nextElementLoader.setVisibility(View.GONE);
+ peertubeNotificationsListAdapter = new PeertubeNotificationsListAdapter(this.notifications);
+ lv_notifications.setAdapter(peertubeNotificationsListAdapter);
+
+ final LinearLayoutManager mLayoutManager;
+ mLayoutManager = new LinearLayoutManager(context);
+ lv_notifications.setLayoutManager(mLayoutManager);
+ lv_notifications.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ if (dy > 0) {
+ int visibleItemCount = mLayoutManager.getChildCount();
+ int totalItemCount = mLayoutManager.getItemCount();
+ int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
+ if (firstVisibleItem + visibleItemCount == totalItemCount) {
+ if (!flag_loading) {
+ flag_loading = true;
+ asyncTask = new RetrievePeertubeNotificationsAsyncTask(context, null, max_id, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ nextElementLoader.setVisibility(View.VISIBLE);
+ }
+ } else {
+ nextElementLoader.setVisibility(View.GONE);
+ }
+ }
+ }
+ });
+ swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh);
+
+ asyncTask = new RetrievePeertubeNotificationsAsyncTask(context, null, null, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return rootView;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ rootView = null;
+ }
+
+ @Override
+ public void onCreate(Bundle saveInstance) {
+ super.onCreate(saveInstance);
+ }
+
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ this.context = context;
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ if (asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
+ asyncTask.cancel(true);
+ }
+
+ public void scrollToTop() {
+ if (lv_notifications != null)
+ lv_notifications.setAdapter(peertubeNotificationsListAdapter);
+ }
+
+
+ public void pullToRefresh() {
+ max_id = null;
+ notifications = new ArrayList<>();
+ firstLoad = true;
+ flag_loading = true;
+ swiped = true;
+ swipeRefreshLayout.setRefreshing(true);
+ asyncTask = new RetrievePeertubeNotificationsAsyncTask(context, null, null, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ @Override
+ public void onRetrievePeertubeNotifications(APIResponse apiResponse, Account account) {
+ mainLoader.setVisibility(View.GONE);
+ nextElementLoader.setVisibility(View.GONE);
+ if (apiResponse.getError() != null) {
+ Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
+ flag_loading = false;
+ swipeRefreshLayout.setRefreshing(false);
+ swiped = false;
+ return;
+ }
+
+ int previousPosition = notifications.size();
+ max_id = apiResponse.getMax_id();
+ List notifications = apiResponse.getPeertubeNotifications();
+ if (!swiped && firstLoad && (notifications == null || notifications.size() == 0))
+ textviewNoAction.setVisibility(View.VISIBLE);
+ else
+ textviewNoAction.setVisibility(View.GONE);
+ if (swiped) {
+ if (previousPosition > 0) {
+ this.notifications.subList(0, previousPosition).clear();
+ peertubeNotificationsListAdapter.notifyItemRangeRemoved(0, previousPosition);
+ }
+ swiped = false;
+ }
+
+ if (notifications != null && notifications.size() > 0) {
+ this.notifications.addAll(notifications);
+ peertubeNotificationsListAdapter.notifyItemRangeInserted(previousPosition, notifications.size());
+ } else {
+ if (firstLoad)
+ textviewNoAction.setVisibility(View.VISIBLE);
+ }
+ swipeRefreshLayout.setRefreshing(false);
+ firstLoad = false;
+ //The initial call comes from a classic tab refresh
+ flag_loading = (max_id == null);
+ }
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayPlaylistsFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayPlaylistsFragment.java
index 95fc27c..cc7212f 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayPlaylistsFragment.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayPlaylistsFragment.java
@@ -16,11 +16,11 @@ package app.fedilab.fedilabtube.fragment;
import android.app.Activity;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.text.InputFilter;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,15 +43,8 @@ import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import net.gotev.uploadservice.MultipartUploadRequest;
-import net.gotev.uploadservice.ServerResponse;
-import net.gotev.uploadservice.UploadInfo;
-import net.gotev.uploadservice.UploadNotificationConfig;
-import net.gotev.uploadservice.UploadStatusDelegate;
-
import org.jetbrains.annotations.NotNull;
-import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -64,10 +57,12 @@ import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeChannelsAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
+import app.fedilab.fedilabtube.client.HttpsConnection;
+import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Playlist;
+import app.fedilab.fedilabtube.client.entities.PlaylistElement;
import app.fedilab.fedilabtube.drawer.PlaylistAdapter;
-import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnPlaylistActionInterface;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
import es.dmoral.toasty.Toasty;
@@ -113,11 +108,6 @@ public class DisplayPlaylistsFragment extends Fragment implements OnPlaylistActi
asyncTask = new ManagePlaylistsAsyncTask(context, ManagePlaylistsAsyncTask.action.GET_PLAYLIST, null, null, null, DisplayPlaylistsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
add_new = rootView.findViewById(R.id.add_new);
-
- LinkedHashMap translations = null;
- if (peertubeInformation != null && peertubeInformation.getTranslations() != null)
- translations = new LinkedHashMap<>(peertubeInformation.getTranslations());
-
LinkedHashMap privaciesInit = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Map.Entry entryInt = privaciesInit.entrySet().iterator().next();
privacyToSend = new HashMap<>();
@@ -131,7 +121,6 @@ public class DisplayPlaylistsFragment extends Fragment implements OnPlaylistActi
if (add_new != null) {
add_new.setOnClickListener(view -> {
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
LayoutInflater inflater1 = ((Activity) context).getLayoutInflater();
View dialogView = inflater1.inflate(R.layout.add_playlist, new LinearLayout(context), false);
@@ -147,97 +136,79 @@ public class DisplayPlaylistsFragment extends Fragment implements OnPlaylistActi
display_name.setFilters(new InputFilter[]{new InputFilter.LengthFilter(120)});
description.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1000)});
- dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
+ dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
- if (display_name.getText() != null && display_name.getText().toString().trim().length() > 0) {
+ if (display_name.getText() != null && display_name.getText().toString().trim().length() > 0) {
- Playlist playlist = new Playlist();
- playlist.setDisplayName(display_name.getText().toString().trim());
- if (description.getText() != null && description.getText().toString().trim().length() > 0) {
- playlist.setDescription(description.getText().toString().trim());
- }
- String idChannel = null;
- if (channelToSend != null) {
- Map.Entry channelM = channelToSend.entrySet().iterator().next();
- idChannel = channelM.getValue();
- if (idChannel.length() > 0)
- playlist.setVideoChannelId(idChannel);
- }
- Map.Entry privacyM = privacyToSend.entrySet().iterator().next();
- String label = privacyM.getValue();
- String idPrivacy = String.valueOf(privacyM.getKey());
- if (label.equals("Public") && (playlist.getVideoChannelId() == null || playlist.getVideoChannelId().equals(""))) {
- Toasty.error(context, context.getString(R.string.error_channel_mandatory), Toast.LENGTH_LONG).show();
- } else {
- if (privacyToSend != null) {
- playlist.setPrivacy(privacyToSend);
- }
- //new ManagePlaylistsAsyncTask(context, ManagePlaylistsAsyncTask.action.CREATE_PLAYLIST, playlist, null, null, DisplayPlaylistsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- UploadNotificationConfig uploadConfig = new UploadNotificationConfig();
- uploadConfig.getCompleted().autoClear = true;
- try {
- String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
- new MultipartUploadRequest(context, "https://" + Helper.getLiveInstance(context) + "/api/v1/video-playlists/")
- //.addFileToUpload(uri.toString().replace("file://",""), "videofile")
- .addHeader("Authorization", "Bearer " + token)
- .setNotificationConfig(uploadConfig)
- // .addParameter("name", filename)
- .addParameter("videoChannelId", idChannel)
- .addParameter("privacy", idPrivacy)
- .addParameter("displayName", playlist.getDisplayName())
- .addParameter("description", playlist.getDescription())
- .setMaxRetries(1)
- .setDelegate(new UploadStatusDelegate() {
- @Override
- public void onProgress(Context context, UploadInfo uploadInfo) {
- // your code here
- }
-
- @Override
- public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
- Exception exception) {
- // your code here
- exception.printStackTrace();
- }
-
- @Override
- public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
- DisplayPlaylistsFragment displayPlaylistsFragment;
- if (getActivity() == null)
- return;
- displayPlaylistsFragment = (DisplayPlaylistsFragment) getActivity().getSupportFragmentManager().findFragmentByTag("PLAYLISTS");
- final FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
- if (displayPlaylistsFragment != null) {
- ft.detach(displayPlaylistsFragment);
- ft.attach(displayPlaylistsFragment);
- ft.commit();
- }
- }
-
- @Override
- public void onCancelled(Context context, UploadInfo uploadInfo) {
- // your code here
- }
- })
- .startUpload();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
-
- dialog.dismiss();
- add_new.setEnabled(false);
- }
- } else {
- Toasty.error(context, context.getString(R.string.error_display_name), Toast.LENGTH_LONG).show();
+ Playlist playlist = new Playlist();
+ playlist.setDisplayName(display_name.getText().toString().trim());
+ if (description.getText() != null && description.getText().toString().trim().length() > 0) {
+ playlist.setDescription(description.getText().toString().trim());
}
+ String idChannel = null;
+ if (channelToSend != null) {
+ Map.Entry channelM = channelToSend.entrySet().iterator().next();
+ idChannel = channelM.getValue();
+ if (idChannel.length() > 0)
+ playlist.setVideoChannelId(idChannel);
+ }
+ Map.Entry privacyM = privacyToSend.entrySet().iterator().next();
+ String label = privacyM.getValue();
+ String idPrivacy = String.valueOf(privacyM.getKey());
+ if (label.equals("Public") && (playlist.getVideoChannelId() == null || playlist.getVideoChannelId().equals(""))) {
+ Toasty.error(context, context.getString(R.string.error_channel_mandatory), Toast.LENGTH_LONG).show();
+ } else {
+ if (privacyToSend != null) {
+ playlist.setPrivacy(privacyToSend);
+ }
+ PlaylistElement playlistElement = new PlaylistElement();
+ playlistElement.setVideoChannelId(idChannel);
+ playlistElement.setPrivacy(idPrivacy);
+ playlistElement.setDisplayName(playlist.getDisplayName());
+ playlistElement.setDescription(playlist.getDescription());
+ new Thread(() -> {
+ try {
+ new PeertubeAPI(context).createPlaylist(playlistElement);
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ DisplayPlaylistsFragment displayPlaylistsFragment;
+ if (getActivity() == null)
+ return;
+ displayPlaylistsFragment = (DisplayPlaylistsFragment) getActivity().getSupportFragmentManager().findFragmentByTag("PLAYLISTS");
+ final FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
+ if (displayPlaylistsFragment != null) {
+ ft.detach(displayPlaylistsFragment);
+ ft.attach(displayPlaylistsFragment);
+ ft.commit();
+ }
+ };
+ mainHandler.post(myRunnable);
+ add_new.setEnabled(true);
+ } catch (HttpsConnection.HttpsConnectionException e) {
+ e.printStackTrace();
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ if (e.getMessage() != null) {
+ Toasty.error(context, e.getMessage(), Toast.LENGTH_LONG).show();
+ } else {
+ Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ }
+ add_new.setEnabled(true);
+ };
+ mainHandler.post(myRunnable);
+ }
+ }).start();
+ dialog.dismiss();
+ add_new.setEnabled(false);
+ }
+ } else {
+ Toasty.error(context, context.getString(R.string.error_display_name), Toast.LENGTH_LONG).show();
}
+
});
dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
-
AlertDialog alertDialog = dialogBuilder.create();
alertDialog.setTitle(getString(R.string.action_playlist_create));
alertDialog.setOnDismissListener(dialogInterface -> {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayStatusFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayStatusFragment.java
index 4ff0343..c194832 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayStatusFragment.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayStatusFragment.java
@@ -44,7 +44,7 @@ import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.R;
-import app.fedilab.fedilabtube.asynctasks.RetrieveAccountSubscriptionsAsyncTask;
+import app.fedilab.fedilabtube.asynctasks.RetrieveAccountsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeSearchAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
@@ -192,7 +192,7 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
- new RetrieveAccountSubscriptionsAsyncTask(context, max_id_accounts, DisplayStatusFragment.this).execute();
+ new RetrieveAccountsAsyncTask(context, max_id_accounts, RetrieveAccountsAsyncTask.accountFetch.SUBSCRIPTION, DisplayStatusFragment.this).execute();
}
}
}
@@ -261,7 +261,7 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
});
}
if (type == PSUBSCRIPTIONS) {
- new RetrieveAccountSubscriptionsAsyncTask(context, max_id, DisplayStatusFragment.this).execute();
+ new RetrieveAccountsAsyncTask(context, max_id, RetrieveAccountsAsyncTask.accountFetch.SUBSCRIPTION, DisplayStatusFragment.this).execute();
}
display_all.setOnClickListener(v -> {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java
new file mode 100644
index 0000000..31139fc
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java
@@ -0,0 +1,109 @@
+package app.fedilab.fedilabtube.fragment;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import java.util.Arrays;
+import java.util.List;
+
+import app.fedilab.fedilabtube.R;
+import app.fedilab.fedilabtube.helper.Helper;
+import es.dmoral.toasty.Toasty;
+
+/* 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 . */
+
+public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ addPreferencesFromResource(R.xml.main_preferences);
+ createPref();
+ }
+
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ getPreferenceScreen().getSharedPreferences()
+ .registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ getPreferenceScreen().getSharedPreferences()
+ .unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key.compareTo(getString(R.string.set_video_mode_choice)) == 0) {
+ ListPreference set_video_mode_choice = findPreference(getString(R.string.set_video_mode_choice));
+ if (set_video_mode_choice != null && getActivity() != null) {
+ SharedPreferences sharedpreferences = getActivity().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ switch (set_video_mode_choice.getValue()) {
+ case "0":
+ editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
+ break;
+ case "1":
+ editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_STREAMING);
+ break;
+ case "2":
+ editor.putInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_WEBVIEW);
+ break;
+ }
+ editor.apply();
+ }
+ }
+ }
+
+ private void createPref() {
+ getPreferenceScreen().removeAll();
+ addPreferencesFromResource(R.xml.main_preferences);
+ PreferenceScreen preferenceScreen = getPreferenceScreen();
+ FragmentActivity context = getActivity();
+ assert context != null;
+ if (preferenceScreen == null) {
+ Toasty.error(getActivity(), getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
+ return;
+ }
+
+ //****** Video mode *******
+ ListPreference set_video_mode_choice = findPreference(getString(R.string.set_video_mode_choice));
+ List array = Arrays.asList(getResources().getStringArray(R.array.settings_video_mode));
+ CharSequence[] entries = array.toArray(new CharSequence[0]);
+ CharSequence[] entryValues = new CharSequence[3];
+ final SharedPreferences sharedpref = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ int video_mode = sharedpref.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL);
+ entryValues[0] = String.valueOf(Helper.VIDEO_MODE_NORMAL);
+ entryValues[1] = String.valueOf(Helper.VIDEO_MODE_STREAMING);
+ entryValues[2] = String.valueOf(Helper.VIDEO_MODE_WEBVIEW);
+ if (set_video_mode_choice != null) {
+ set_video_mode_choice.setEntries(entries);
+ set_video_mode_choice.setEntryValues(entryValues);
+ set_video_mode_choice.setValueIndex(video_mode);
+ }
+
+ }
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java
index 8ebf56f..3160b56 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java
@@ -72,10 +72,13 @@ public class Helper {
public static final int RELOAD_MYVIDEOS = 10;
public static final String SET_VIDEO_MODE = "set_video_mode";
- public static final int VIDEO_MODE_TORRENT = 0;
- public static final int VIDEO_MODE_WEBVIEW = 1;
- public static final int VIDEO_MODE_DIRECT = 2;
+ public static final int VIDEO_MODE_NORMAL = 0;
+ public static final int VIDEO_MODE_STREAMING = 1;
+ public static final int VIDEO_MODE_WEBVIEW = 2;
+ public static final int VIDEO_MODE_TORRENT = 3;
public static final int ADD_USER_INTENT = 5;
+ public static final int VIDEO_UPLOADED_INTENT = 6;
+ public static final String VIDEO_UPLOAD_ID = "VIDEO_UPLOAD_ID";
public static final String SET_SHARE_DETAILS = "set_share_details";
public static final int DEFAULT_VIDEO_CACHE_MB = 100;
public static final String TAG = "mastodon_etalab";
@@ -239,6 +242,9 @@ public class Helper {
public static String getLiveInstance(Context context) {
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String acad = sharedpreferences.getString(Helper.PREF_INSTANCE, "tube.ac-lyon.fr");
+ if (acad == null) {
+ acad = "tube.ac-lyon.fr";
+ }
if (acad.startsWith("tube-")) {
return acad;
} else {
@@ -449,6 +455,14 @@ public class Helper {
public static void loadGiF(final Context context, String url, final ImageView imageView) {
+ if (url == null || url.trim().toLowerCase().compareTo("null") == 0) {
+ Glide.with(imageView.getContext())
+ .asDrawable()
+ .load(R.drawable.missing_peertube)
+ .apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
+ .into(imageView);
+ return;
+ }
if (url.startsWith("/")) {
url = Helper.getLiveInstance(context) + url;
}
@@ -668,4 +682,5 @@ public class Helper {
return context.getResources().getBoolean(R.bool.is_tablet);
}
+
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/services/PeertubeUploadReceiver.java b/app/src/main/java/app/fedilab/fedilabtube/services/PeertubeUploadReceiver.java
index d059ef7..a31f5e5 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/services/PeertubeUploadReceiver.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/services/PeertubeUploadReceiver.java
@@ -14,6 +14,7 @@ package app.fedilab.fedilabtube.services;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -43,9 +44,9 @@ public class PeertubeUploadReceiver extends UploadServiceBroadcastReceiver {
@Override
public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
Exception exception) {
- // your code here
}
+ @SuppressLint("ApplySharedPref")
@Override
public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
try {
diff --git a/app/src/main/res/drawable/ic_baseline_arrow_white_24.xml b/app/src/main/res/drawable/ic_baseline_arrow_white_24.xml
index fa122e1..5d09b98 100644
--- a/app/src/main/res/drawable/ic_baseline_arrow_white_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_arrow_white_24.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_delete_24.xml b/app/src/main/res/drawable/ic_baseline_delete_24.xml
new file mode 100644
index 0000000..c710ac7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_delete_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_history_24.xml b/app/src/main/res/drawable/ic_baseline_history_24.xml
new file mode 100644
index 0000000..d42359c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_history_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_slow_motion_video_24.xml b/app/src/main/res/drawable/ic_baseline_slow_motion_video_24.xml
new file mode 100644
index 0000000..1804da2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_slow_motion_video_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_volume_mute_24.xml b/app/src/main/res/drawable/ic_baseline_volume_mute_24.xml
new file mode 100644
index 0000000..1f8aef5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_volume_mute_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml
new file mode 100644
index 0000000..135dbdf
--- /dev/null
+++ b/app/src/main/res/layout/activity_account.xml
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_all_playlist.xml b/app/src/main/res/layout/activity_all_playlist.xml
index 76dac5d..3318606 100644
--- a/app/src/main/res/layout/activity_all_playlist.xml
+++ b/app/src/main/res/layout/activity_all_playlist.xml
@@ -52,9 +52,7 @@
android:gravity="center"
android:padding="10dp"
android:text="@string/action_playlist_add"
- android:textSize="25sp"
- android:textStyle="italic|bold"
- android:typeface="serif" />
+ android:textSize="25sp" />
.
-->
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
-
+
+
+
+
+
+
+
+
+
+ android:paddingStart="50dp"
+ android:paddingEnd="50dp">
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:hint="@string/email_address"
+ android:inputType="textEmailAddress"
+ android:singleLine="true" />
-
+
+
+
+
+ android:hint="@string/password"
+ android:inputType="textPassword"
+ android:singleLine="true" />
-
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="10dp">
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_peertube.xml b/app/src/main/res/layout/activity_peertube.xml
index 74f064f..b4ce257 100644
--- a/app/src/main/res/layout/activity_peertube.xml
+++ b/app/src/main/res/layout/activity_peertube.xml
@@ -112,10 +112,10 @@
android:layout_marginLeft="10dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
- android:drawableTop="@drawable/ic_baseline_visibility_24"
android:drawablePadding="5dp"
android:gravity="center_horizontal"
android:text="0"
+ app:drawableTopCompat="@drawable/ic_baseline_visibility_24"
tools:ignore="HardcodedText" />
+ android:text=""
+ app:drawableTopCompat="@drawable/ic_baseline_bookmark_border_24" />
+ android:visibility="gone"
+ app:drawableTopCompat="@drawable/ic_baseline_list_24" />
+ android:textSize="12sp"
+ app:drawableTopCompat="@drawable/ic_baseline_share_24" />
+ android:textSize="12sp"
+ app:drawableTopCompat="@drawable/ic_baseline_cloud_upload_24" />
+ android:textSize="25sp" />
diff --git a/app/src/main/res/layout/activity_peertube_edit.xml b/app/src/main/res/layout/activity_peertube_edit.xml
index 429df13..4542ca5 100644
--- a/app/src/main/res/layout/activity_peertube_edit.xml
+++ b/app/src/main/res/layout/activity_peertube_edit.xml
@@ -45,6 +45,36 @@
android:inputType="text" />
+
+
+
+
+
+
+
+
+
+
+ android:textSize="25sp" />
.
-->
-
-
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp">
+ app:layout_constraintTop_toTopOf="parent" />
+ android:textSize="18sp"
+ app:layout_constraintBottom_toTopOf="@+id/subscriber_count"
+ app:layout_constraintStart_toEndOf="@+id/account_pp"
+ app:layout_constraintTop_toTopOf="@+id/account_pp" />
+ app:layout_constraintStart_toEndOf="@+id/account_pp"
+ app:layout_constraintTop_toBottomOf="@id/account_dn" />
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/add_channel.xml b/app/src/main/res/layout/add_channel.xml
new file mode 100644
index 0000000..00a9b18
--- /dev/null
+++ b/app/src/main/res/layout/add_channel.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/drawer_account.xml b/app/src/main/res/layout/drawer_account.xml
index e99a75f..659ff31 100644
--- a/app/src/main/res/layout/drawer_account.xml
+++ b/app/src/main/res/layout/drawer_account.xml
@@ -148,25 +148,17 @@
-
-
-
-
-
+ android:layout_margin="5dp"
+ android:contentDescription="@string/action_follow"
+ android:gravity="center"
+ android:scaleType="fitXY"
+ android:visibility="gone"
+ app:backgroundTint="?colorAccent"
+ app:fabSize="mini" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_horizontal_account.xml b/app/src/main/res/layout/drawer_horizontal_account.xml
index 870ed06..0f583f0 100644
--- a/app/src/main/res/layout/drawer_horizontal_account.xml
+++ b/app/src/main/res/layout/drawer_horizontal_account.xml
@@ -19,13 +19,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
+ android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:orientation="vertical">
+ android:singleLine="true" />
.
-->
+
+
-
-
\ No newline at end of file
+ android:layout_height="wrap_content">
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_peertube_favourites.xml b/app/src/main/res/layout/fragment_peertube_favourites.xml
index 78fab32..c190208 100644
--- a/app/src/main/res/layout/fragment_peertube_favourites.xml
+++ b/app/src/main/res/layout/fragment_peertube_favourites.xml
@@ -39,9 +39,7 @@
android:gravity="center"
android:padding="10dp"
android:text="@string/bookmark_peertube_empty"
- android:textSize="25sp"
- android:textStyle="italic|bold"
- android:typeface="serif" />
+ android:textSize="25sp" />
+ android:textSize="25sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_video.xml b/app/src/main/res/layout/fragment_video.xml
index 36deba8..b49335a 100644
--- a/app/src/main/res/layout/fragment_video.xml
+++ b/app/src/main/res/layout/fragment_video.xml
@@ -90,9 +90,7 @@
android:gravity="center"
android:padding="10dp"
android:text="@string/no_videos"
- android:textSize="25sp"
- android:textStyle="italic|bold"
- android:typeface="serif" />
+ android:textSize="25sp" />
+
diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml
index e8f3994..c467c25 100644
--- a/app/src/main/res/menu/main_menu.xml
+++ b/app/src/main/res/menu/main_menu.xml
@@ -35,4 +35,9 @@
android:icon="@drawable/ic_baseline_personal_video_24"
android:title="@string/my_videos"
app:showAsAction="ifRoom" />
+
diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml
index 6cbaa0c..d0230d8 100644
--- a/app/src/main/res/values-sw600dp/dimens.xml
+++ b/app/src/main/res/values-sw600dp/dimens.xml
@@ -2,4 +2,5 @@
true
150dp
+ 100dp
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 9406300..c835954 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -3,6 +3,7 @@
16dp
16dp
5dp
+ 16dp
2dp
100dp
16dp
@@ -10,4 +11,5 @@
false
0dp
20dp
+ 10dp
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a597167..ced43c3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -147,11 +147,14 @@
Voulez-vous vraiment déconnecter le compte @%1$s ?
Supprimer la liste de lecture
+ Supprimer la chaîne
Êtes-vous sûr de vouloir supprimer définitivement cette liste de lecture ?
+ Êtes-vous sûr de vouloir supprimer définitivement cette chaîne ?
Créer une liste de lecture
Nom d\'affichage
Un canal est requis lorsque la liste de lecture est publique.
Vous devez fournir un nom d\'affichage !
+ Vous devez fournir un nom d\'affichage et un nom pour la chaîne!
Cette liste de lecture est vide.
Listes de lecture
Aucune notification à afficher
@@ -176,4 +179,32 @@
La vidéo a été signalée !
Veuillez préciser les raisons.
Tout
+ Historique
+ Modifier une vidéo
+ Paramètres
+
+
+ - Normal
+ - Streaming
+ - Navigateur
+
+
+
+ set_video_mode_choice
+ Permet de changer le mode de lecture pour les vidéos (normal, streaming ou via un navigateur).
+ Créer un compte
+ Aperçu
+ Modifier l\'aperçu
+ Sourdine
+ Bloqués
+ Aucun compte en sourdine !
+ Mettre en sourdine
+ Réactiver le compte
+ Le compte a été mis en sourdine !
+ Chaînes
+ Nom
+ Créer une chaîne
+ Supprimer la chaîne
+ Afficher la liste
+ Supprimer la liste de lecture
\ No newline at end of file
diff --git a/app/src/main/res/xml/main_preferences.xml b/app/src/main/res/xml/main_preferences.xml
new file mode 100644
index 0000000..32b5353
--- /dev/null
+++ b/app/src/main/res/xml/main_preferences.xml
@@ -0,0 +1,11 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 6354122..41b981d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -22,5 +22,4 @@ allprojects {
task clean(type: Delete) {
delete rootProject.buildDir
-}
-
+}
\ No newline at end of file