diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dbad8e1..c55b5a0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -83,7 +83,11 @@ android:configChanges="orientation|screenSize" android:label="@string/app_name" android:windowSoftInputMode="stateAlwaysHidden" /> - + + . */ + + +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import java.util.ArrayList; +import java.util.List; + +import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist; +import app.fedilab.fedilabtube.client.data.VideoPlaylistData; +import app.fedilab.fedilabtube.drawer.PlaylistAdapter; +import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; +import es.dmoral.toasty.Toasty; + + +public class AllLocalPlaylistsActivity extends AppCompatActivity implements PlaylistAdapter.AllPlaylistRemoved { + + + PlaylistAdapter playlistAdapter; + private RelativeLayout mainLoader; + private RelativeLayout textviewNoAction; + private List playlists; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_all_playlist); + + if (getSupportActionBar() != null) + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + setTitle(R.string.playlists); + + + textviewNoAction = findViewById(R.id.no_action); + mainLoader = findViewById(R.id.loader); + RelativeLayout nextElementLoader = findViewById(R.id.loading_next_items); + mainLoader.setVisibility(View.VISIBLE); + nextElementLoader.setVisibility(View.GONE); + + PlaylistsVM viewModel = new ViewModelProvider(AllLocalPlaylistsActivity.this).get(PlaylistsVM.class); + viewModel.localePlaylist().observe(AllLocalPlaylistsActivity.this, this::manageVIewPlaylists); + + FloatingActionButton add_new = findViewById(R.id.add_new); + add_new.setVisibility(View.GONE); + + + playlists = new ArrayList<>(); + RecyclerView lv_playlist = findViewById(R.id.lv_playlist); + playlistAdapter = new PlaylistAdapter(playlists, true); + lv_playlist.setAdapter(playlistAdapter); + LinearLayoutManager mLayoutManager = new LinearLayoutManager(AllLocalPlaylistsActivity.this); + lv_playlist.setLayoutManager(mLayoutManager); + + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + + public void manageVIewPlaylists(List videoPlaylistExports) { + mainLoader.setVisibility(View.GONE); + if (videoPlaylistExports == null) { + Toasty.error(AllLocalPlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); + return; + } + if (videoPlaylistExports.size() > 0) { + for (VideoPlaylistData.VideoPlaylistExport videoPlaylistExport : videoPlaylistExports) { + playlists.add(videoPlaylistExport.getPlaylist()); + } + playlistAdapter.notifyDataSetChanged(); + textviewNoAction.setVisibility(View.GONE); + } else { + textviewNoAction.setVisibility(View.VISIBLE); + } + } + + @Override + public void onAllPlaylistRemoved() { + textviewNoAction.setVisibility(View.VISIBLE); + } + +} diff --git a/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java b/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java index bc18507..493cefe 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/AllPlaylistsActivity.java @@ -29,7 +29,6 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; -import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.Toast; @@ -37,6 +36,8 @@ import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -61,7 +62,7 @@ import es.dmoral.toasty.Toasty; import static app.fedilab.fedilabtube.MainActivity.peertubeInformation; -public class AllPlaylistsActivity extends AppCompatActivity { +public class AllPlaylistsActivity extends AppCompatActivity implements PlaylistAdapter.AllPlaylistRemoved { PlaylistAdapter playlistAdapter; @@ -109,10 +110,11 @@ public class AllPlaylistsActivity extends AppCompatActivity { playlists = new ArrayList<>(); - ListView lv_playlist = findViewById(R.id.lv_playlist); - playlistAdapter = new PlaylistAdapter(AllPlaylistsActivity.this, playlists, textviewNoAction); + RecyclerView lv_playlist = findViewById(R.id.lv_playlist); + playlistAdapter = new PlaylistAdapter(playlists, false); lv_playlist.setAdapter(playlistAdapter); - + LinearLayoutManager mLayoutManager = new LinearLayoutManager(AllPlaylistsActivity.this); + lv_playlist.setLayoutManager(mLayoutManager); add_new.setOnClickListener(view -> manageAlert(null)); } @@ -378,4 +380,9 @@ public class AllPlaylistsActivity extends AppCompatActivity { set_upload_channel.setSelection(position); } } + + @Override + public void onAllPlaylistRemoved() { + textviewNoAction.setVisibility(View.VISIBLE); + } } diff --git a/app/src/main/java/app/fedilab/fedilabtube/LocalPlaylistsActivity.java b/app/src/main/java/app/fedilab/fedilabtube/LocalPlaylistsActivity.java new file mode 100644 index 0000000..653e500 --- /dev/null +++ b/app/src/main/java/app/fedilab/fedilabtube/LocalPlaylistsActivity.java @@ -0,0 +1,79 @@ +package app.fedilab.fedilabtube; +/* Copyright 2020 Thomas Schneider + * + * This file is a part of TubeLab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with TubeLab; if not, + * see . */ + +import android.os.Bundle; +import android.view.MenuItem; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.FragmentTransaction; + +import app.fedilab.fedilabtube.client.data.PlaylistData; +import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; +import app.fedilab.fedilabtube.helper.Helper; +import app.fedilab.fedilabtube.viewmodel.TimelineVM; +import es.dmoral.toasty.Toasty; + + +public class LocalPlaylistsActivity extends AppCompatActivity { + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (getSupportActionBar() != null) + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + + setContentView(R.layout.activity_playlists); + + + PlaylistData.Playlist playlist; + Bundle b = getIntent().getExtras(); + if (b != null) { + playlist = b.getParcelable("playlist"); + if (playlist == null) { + return; + } + } else { + Toasty.error(LocalPlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); + return; + } + setTitle(playlist.getDisplayName()); + if (savedInstanceState == null) { + DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.VIDEOS_IN_LOCAL_PLAYLIST); + bundle.putSerializable("playlistId", playlist.getUuid()); + displayVideosFragment.setArguments(bundle); + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.add(R.id.nav_host_fragment, displayVideosFragment).commit(); + } + + } + + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java index 9c1e99a..b2d0c83 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java @@ -465,7 +465,7 @@ public class MainActivity extends AppCompatActivity { instanceItem.setVisible(true); uploadItem.setVisible(false); myVideosItem.setVisible(false); - playslistItem.setVisible(false); + playslistItem.setVisible(!BuildConfig.full_instances); historyItem.setVisible(false); settingsItem.setVisible(true); mostLikedItem.setVisible(false); @@ -563,7 +563,12 @@ public class MainActivity extends AppCompatActivity { startActivity(intent); return true; } else if (item.getItemId() == R.id.action_playlist) { - Intent intent = new Intent(MainActivity.this, AllPlaylistsActivity.class); + Intent intent; + if (Helper.isLoggedIn(MainActivity.this)) { + intent = new Intent(MainActivity.this, AllPlaylistsActivity.class); + } else { + intent = new Intent(MainActivity.this, AllLocalPlaylistsActivity.class); + } startActivity(intent); return true; } else if (item.getItemId() == R.id.action_sepia_search) { diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/PlaylistAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/PlaylistAdapter.java index d697dd2..9e74300 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/drawer/PlaylistAdapter.java +++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/PlaylistAdapter.java @@ -15,11 +15,13 @@ package app.fedilab.fedilabtube.drawer; * see . */ import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; @@ -30,13 +32,9 @@ import android.os.Looper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.TextView; + +import androidx.annotation.NonNull; import androidx.appcompat.widget.PopupMenu; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -44,6 +42,7 @@ import androidx.core.content.FileProvider; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelStoreOwner; +import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.FutureTarget; @@ -56,85 +55,73 @@ import java.util.concurrent.ExecutionException; import app.fedilab.fedilabtube.AllPlaylistsActivity; import app.fedilab.fedilabtube.BuildConfig; +import app.fedilab.fedilabtube.LocalPlaylistsActivity; import app.fedilab.fedilabtube.MainActivity; import app.fedilab.fedilabtube.PlaylistsActivity; import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist; -import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.data.VideoPlaylistData; +import app.fedilab.fedilabtube.databinding.DrawerPlaylistBinding; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.NotificationHelper; import app.fedilab.fedilabtube.helper.PlaylistExportHelper; +import app.fedilab.fedilabtube.sqlite.ManagePlaylistsDAO; +import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; import es.dmoral.toasty.Toasty; import static app.fedilab.fedilabtube.viewmodel.PlaylistsVM.action.GET_LIST_VIDEOS; -public class PlaylistAdapter extends BaseAdapter { +public class PlaylistAdapter extends RecyclerView.Adapter { private final List playlists; - private final LayoutInflater layoutInflater; - private final Context context; - private final RelativeLayout textviewNoAction; + private final boolean locale; + public AllPlaylistRemoved allPlaylistRemoved; + private Context context; - public PlaylistAdapter(Context context, List lists, RelativeLayout textviewNoAction) { + public PlaylistAdapter(List lists, boolean locale) { this.playlists = lists; - layoutInflater = LayoutInflater.from(context); - this.context = context; - this.textviewNoAction = textviewNoAction; + this.locale = locale; } + @NonNull @Override - public int getCount() { - return playlists.size(); + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + context = parent.getContext(); + DrawerPlaylistBinding itemBinding = DrawerPlaylistBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + return new ViewHolder(itemBinding); } + @SuppressLint({"SetJavaScriptEnabled", "ClickableViewAccessibility"}) @Override - public Object getItem(int position) { - return playlists.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - - @Override - public View getView(final int position, View convertView, ViewGroup parent) { + public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int position) { + context = viewHolder.itemView.getContext(); + final ViewHolder holder = (ViewHolder) viewHolder; final Playlist playlist = playlists.get(position); - final ViewHolder holder; - if (convertView == null) { - convertView = layoutInflater.inflate(R.layout.drawer_playlist, parent, false); - holder = new ViewHolder(); - holder.preview_title = convertView.findViewById(R.id.preview_title); - holder.preview_visibility = convertView.findViewById(R.id.preview_visibility); - holder.preview_description = convertView.findViewById(R.id.preview_description); - holder.playlist_container = convertView.findViewById(R.id.playlist_container); - holder.preview_playlist = convertView.findViewById(R.id.preview_playlist); - holder.playlist_more = convertView.findViewById(R.id.playlist_more); - convertView.setTag(holder); + String imgUrl; + + if (locale) { + imgUrl = "https://" + playlist.getOwnerAccount().getHost() + playlist.getThumbnailPath(); } else { - holder = (ViewHolder) convertView.getTag(); + imgUrl = playlist.getThumbnailPath(); } + Helper.loadGiF(context, imgUrl, holder.binding.previewPlaylist); - Helper.loadGiF(context, playlist.getThumbnailPath(), holder.preview_playlist); - - holder.preview_title.setText(playlist.getDisplayName()); + holder.binding.previewTitle.setText(playlist.getDisplayName()); if (playlist.getDescription() != null && playlist.getDescription().trim().compareTo("null") != 0 && playlist.getDescription().length() > 0) { - holder.preview_description.setText(playlist.getDescription()); - holder.preview_description.setVisibility(View.VISIBLE); + holder.binding.previewDescription.setText(playlist.getDescription()); + holder.binding.previewDescription.setVisibility(View.VISIBLE); } else { - holder.preview_description.setVisibility(View.GONE); + holder.binding.previewDescription.setVisibility(View.GONE); } - holder.preview_visibility.setText(playlist.getPrivacy().getLabel()); + holder.binding.previewVisibility.setText(playlist.getPrivacy().getLabel()); - holder.playlist_container.setOnClickListener(v -> { - Intent intent = new Intent(context, PlaylistsActivity.class); + holder.binding.playlistContainer.setOnClickListener(v -> { + Intent intent = new Intent(context, locale ? LocalPlaylistsActivity.class : PlaylistsActivity.class); Bundle b = new Bundle(); b.putParcelable("playlist", playlist); intent.putExtras(b); @@ -142,18 +129,22 @@ public class PlaylistAdapter extends BaseAdapter { }); if (playlist.getDisplayName().compareTo("Watch later") == 0) { - holder.playlist_more.setVisibility(View.GONE); + holder.binding.playlistMore.setVisibility(View.GONE); } else { - holder.playlist_more.setVisibility(View.VISIBLE); + holder.binding.playlistMore.setVisibility(View.VISIBLE); } - holder.playlist_more.setOnClickListener(v -> { - PopupMenu popup = new PopupMenu(context, holder.playlist_more); + holder.binding.playlistMore.setOnClickListener(v -> { + PopupMenu popup = new PopupMenu(context, holder.binding.playlistMore); popup.getMenuInflater() .inflate(R.menu.playlist_menu, popup.getMenu()); if (!BuildConfig.full_instances) { popup.getMenu().findItem(R.id.action_export).setVisible(true); } + if (locale) { + popup.getMenu().findItem(R.id.action_export).setVisible(false); + popup.getMenu().findItem(R.id.action_edit).setVisible(false); + } popup.setOnMenuItemClickListener(item -> { int itemId = item.getItemId(); if (itemId == R.id.action_delete) { @@ -164,11 +155,18 @@ public class PlaylistAdapter extends BaseAdapter { .setPositiveButton(R.string.yes, (dialog, which) -> { playlists.remove(playlist); notifyDataSetChanged(); - PlaylistsVM viewModel = new ViewModelProvider((ViewModelStoreOwner) context).get(PlaylistsVM.class); - viewModel.manage(PlaylistsVM.action.DELETE_PLAYLIST, playlist, null).observe((LifecycleOwner) context, apiResponse -> manageVIewPlaylists(PlaylistsVM.action.DELETE_PLAYLIST, apiResponse)); - - if (playlists.size() == 0 && textviewNoAction != null && textviewNoAction.getVisibility() == View.GONE) - textviewNoAction.setVisibility(View.VISIBLE); + if (!locale) { + PlaylistsVM viewModel = new ViewModelProvider((ViewModelStoreOwner) context).get(PlaylistsVM.class); + viewModel.manage(PlaylistsVM.action.DELETE_PLAYLIST, playlist, null).observe((LifecycleOwner) context, apiResponse -> manageVIewPlaylists(PlaylistsVM.action.DELETE_PLAYLIST, apiResponse)); + } else { + new Thread(() -> { + SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + new ManagePlaylistsDAO(context, db).removePlaylist(playlist.getUuid()); + }).start(); + } + if (playlists.size() == 0) { + allPlaylistRemoved.onAllPlaylistRemoved(); + } dialog.dismiss(); }) .setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss()) @@ -193,12 +191,16 @@ public class PlaylistAdapter extends BaseAdapter { popup.show(); }); - return convertView; } - @SuppressWarnings({"unused", "RedundantSuppression"}) - public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) { + @Override + public long getItemId(int position) { + return position; + } + @Override + public int getItemCount() { + return playlists.size(); } private void doExport(Playlist playlist) { @@ -219,10 +221,11 @@ public class PlaylistAdapter extends BaseAdapter { File root = new File(Environment.getExternalStorageDirectory(), context.getString(R.string.app_name)); if (!root.exists()) { + //noinspection ResultOfMethodCallIgnored root.mkdirs(); } file = new File(root, "playlist_" + playlist.getUuid() + ".tubelab"); - FileWriter writer = null; + FileWriter writer; try { writer = new FileWriter(file); writer.append(data); @@ -265,11 +268,23 @@ public class PlaylistAdapter extends BaseAdapter { }).start(); } - private static class ViewHolder { - LinearLayout playlist_container; - ImageView preview_playlist; - TextView preview_title, preview_visibility, preview_description; - ImageButton playlist_more; + + @SuppressWarnings({"unused", "RedundantSuppression"}) + public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) { + + } + + public interface AllPlaylistRemoved { + void onAllPlaylistRemoved(); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + DrawerPlaylistBinding binding; + + ViewHolder(DrawerPlaylistBinding itemView) { + super(itemView.getRoot()); + binding = itemView; + } } } \ No newline at end of file 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 23c89c2..7fa0c0d 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayPlaylistsFragment.java +++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayPlaylistsFragment.java @@ -39,6 +39,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -93,14 +94,14 @@ public class DisplayPlaylistsFragment extends Fragment { playlists = new ArrayList<>(); - ListView lv_playlist = rootView.findViewById(R.id.lv_playlist); + RecyclerView lv_playlist = rootView.findViewById(R.id.lv_playlist); textviewNoAction = rootView.findViewById(R.id.no_action); mainLoader = rootView.findViewById(R.id.loader); RelativeLayout nextElementLoader = rootView.findViewById(R.id.loading_next_items); mainLoader.setVisibility(View.VISIBLE); nextElementLoader.setVisibility(View.GONE); playlists = new ArrayList<>(); - playlistAdapter = new PlaylistAdapter(context, playlists, textviewNoAction); + playlistAdapter = new PlaylistAdapter(playlists, false); lv_playlist.setAdapter(playlistAdapter); PlaylistsVM viewModel = new ViewModelProvider(this).get(PlaylistsVM.class); viewModel.manage(PlaylistsVM.action.GET_PLAYLISTS, null, null).observe(DisplayPlaylistsFragment.this.requireActivity(), apiResponse -> manageVIewPlaylists(PlaylistsVM.action.GET_PLAYLISTS, apiResponse)); diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java index dde9739..14e7599 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java +++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java @@ -506,6 +506,8 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta viewModelFeeds.getVideosInChannel(sepiaSearch ? remoteInstance : null, channelId, max_id).observe(this.requireActivity(), this::manageVIewVideos); } else if (type == TimelineVM.TimelineType.VIDEOS_IN_PLAYLIST) { viewModelFeeds.loadVideosInPlaylist(playlistId, max_id).observe(this.requireActivity(), this::manageVIewVideos); + } else if (type == TimelineVM.TimelineType.VIDEOS_IN_LOCAL_PLAYLIST) { + viewModelFeeds.loadVideosInLocalPlaylist(playlistId).observe(this.requireActivity(), this::manageVIewVideos); } else if (type == TimelineVM.TimelineType.HISTORY) { viewModelFeeds.getVideoHistory(max_id, startDate, endDate).observe(this.requireActivity(), this::manageVIewVideos); } else { diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java index 0b647e5..ab8d43d 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java +++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java @@ -274,9 +274,13 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared Resources resources = getResources(); Drawable defaultAvatar = ResourcesCompat.getDrawable(resources, R.drawable.missing_peertube, null); my_account.setIcon(defaultAvatar); + String avatarUrl = null; + if (userMe.getAccount().getAvatar() != null) { + avatarUrl = "https://" + Helper.getLiveInstance(context) + userMe.getAccount().getAvatar().getPath(); + } Glide.with(getActivity()) .asDrawable() - .load("https://" + Helper.getLiveInstance(context) + userMe.getAccount().getAvatar().getPath()) + .load(avatarUrl != null ? avatarUrl : R.drawable.missing_peertube) .into(new CustomTarget() { @Override public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { diff --git a/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java b/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java index 998c228..582ff14 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java +++ b/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java @@ -26,7 +26,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Scanner; -import app.fedilab.fedilabtube.PlaylistsActivity; +import app.fedilab.fedilabtube.AllLocalPlaylistsActivity; import app.fedilab.fedilabtube.client.data.VideoPlaylistData; import app.fedilab.fedilabtube.sqlite.ManagePlaylistsDAO; import app.fedilab.fedilabtube.sqlite.Sqlite; @@ -106,7 +106,7 @@ public class PlaylistExportHelper { new ManagePlaylistsDAO(activity, db).insertPlaylist(videoPlaylistExport); } activity.runOnUiThread(() -> { - Intent intentPlaylist = new Intent(activity, PlaylistsActivity.class); + Intent intentPlaylist = new Intent(activity, AllLocalPlaylistsActivity.class); activity.startActivity(intentPlaylist); }); }).start(); diff --git a/app/src/main/java/app/fedilab/fedilabtube/sqlite/ManagePlaylistsDAO.java b/app/src/main/java/app/fedilab/fedilabtube/sqlite/ManagePlaylistsDAO.java index b5d99b4..27605c4 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/sqlite/ManagePlaylistsDAO.java +++ b/app/src/main/java/app/fedilab/fedilabtube/sqlite/ManagePlaylistsDAO.java @@ -111,7 +111,7 @@ public class ManagePlaylistsDAO { */ public boolean insertPlaylist(VideoPlaylistData.VideoPlaylistExport videoPlaylistExport) { - if (videoPlaylistExport.getPlaylist() == null || checkExists(videoPlaylistExport.getPlaylist().getUuid())) { + if (videoPlaylistExport.getPlaylist() == null) { return true; } ContentValues values = new ContentValues(); @@ -120,8 +120,15 @@ public class ManagePlaylistsDAO { values.put(Sqlite.COL_PLAYLIST, playlistToStringStorage(videoPlaylistExport.getPlaylist())); //Inserts playlist try { - long playlist_id = db.insertOrThrow(Sqlite.TABLE_LOCAL_PLAYLISTS, null, values); - videoPlaylistExport.setPlaylistDBkey(playlist_id); + long id = checkExists(videoPlaylistExport.getPlaylist().getUuid()); + if (id != -1) { + videoPlaylistExport.setPlaylistDBkey(id); + removeAllVideosInPlaylist(id); + + } else { + long playlist_id = db.insertOrThrow(Sqlite.TABLE_LOCAL_PLAYLISTS, null, values); + videoPlaylistExport.setPlaylistDBkey(playlist_id); + } for (VideoPlaylistData.VideoPlaylist videoPlaylist : videoPlaylistExport.getVideos()) { //Insert videos insertVideos(videoPlaylist.getVideo(), videoPlaylistExport); @@ -143,7 +150,7 @@ public class ManagePlaylistsDAO { */ private boolean insertVideos(VideoData.Video video, VideoPlaylistData.VideoPlaylistExport playlist) { - if (video == null || playlist == null || checkVideoExists(video.getUuid(), playlist.getUuid())) { + if (video == null || playlist == null) { return true; } ContentValues values = new ContentValues(); @@ -166,15 +173,15 @@ public class ManagePlaylistsDAO { * @param uuid String * @return int */ - private boolean checkExists(String uuid) { + private long checkExists(String uuid) { try { Cursor c = db.query(Sqlite.TABLE_LOCAL_PLAYLISTS, null, Sqlite.COL_UUID + " = \"" + uuid + "\"", null, null, null, null, "1"); - int count = c.getCount(); + VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = cursorToSingleVideoPlaylistExport(c); c.close(); - return count > 0; + return videoPlaylistExport != null ? videoPlaylistExport.getPlaylistDBkey() : -1; } catch (Exception e) { e.printStackTrace(); - return false; + return -1; } } @@ -202,6 +209,16 @@ public class ManagePlaylistsDAO { } + /** + * Remove all videos in playlist + * + * @param playlistDBid long db id + * @return int + */ + public int removeAllVideosInPlaylist(long playlistDBid) { + return db.delete(Sqlite.TABLE_VIDEOS, Sqlite.COL_PLAYLIST_ID + " = '" + playlistDBid + "'", null); + } + /** * Remove a playlist with its uuid @@ -266,6 +283,22 @@ public class ManagePlaylistsDAO { } } + /** + * Returns all videos in a playlist + * + * @return List + */ + public List getAllVideosInPlaylist(String uuid) { + try { + VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = getSinglePlaylists(uuid); + Cursor c = db.query(Sqlite.TABLE_VIDEOS, null, Sqlite.COL_PLAYLIST_ID + "='" + videoPlaylistExport.getPlaylistDBkey() + "'", null, null, null, Sqlite.COL_ID + " DESC", null); + return cursorToVideoExport(c); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + /*** * Method to hydrate VideoPlaylistExport from database diff --git a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PlaylistsVM.java b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PlaylistsVM.java index 78739d9..9675907 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PlaylistsVM.java +++ b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PlaylistsVM.java @@ -33,13 +33,16 @@ import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.AccountData.Account; import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist; +import app.fedilab.fedilabtube.client.data.VideoPlaylistData; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.sqlite.AccountDAO; +import app.fedilab.fedilabtube.sqlite.ManagePlaylistsDAO; import app.fedilab.fedilabtube.sqlite.Sqlite; public class PlaylistsVM extends AndroidViewModel { private MutableLiveData apiResponseMutableLiveData; + private MutableLiveData> videoPlaylistExportMutableLiveData; public PlaylistsVM(@NonNull Application application) { super(application); @@ -51,6 +54,13 @@ public class PlaylistsVM extends AndroidViewModel { return apiResponseMutableLiveData; } + public LiveData> localePlaylist() { + videoPlaylistExportMutableLiveData = new MutableLiveData<>(); + loadLocalePlaylist(); + return videoPlaylistExportMutableLiveData; + } + + public LiveData videoExists(List videoIds) { apiResponseMutableLiveData = new MutableLiveData<>(); checkVideosExist(videoIds); @@ -67,6 +77,22 @@ public class PlaylistsVM extends AndroidViewModel { }).start(); } + + private void loadLocalePlaylist() { + Context _mContext = getApplication().getApplicationContext(); + new Thread(() -> { + try { + SQLiteDatabase db = Sqlite.getInstance(_mContext.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + List videoPlaylistExports = new ManagePlaylistsDAO(_mContext, db).getAllPlaylists(); + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> videoPlaylistExportMutableLiveData.setValue(videoPlaylistExports); + mainHandler.post(myRunnable); + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + } + private void managePlaylists(action apiAction, Playlist playlist, String videoId) { Context _mContext = getApplication().getApplicationContext(); new Thread(() -> { diff --git a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java index ad6f334..fd702cc 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java +++ b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java @@ -16,6 +16,7 @@ package app.fedilab.fedilabtube.viewmodel; import android.app.Application; import android.content.Context; +import android.database.sqlite.SQLiteDatabase; import android.os.Handler; import android.os.Looper; @@ -24,9 +25,15 @@ import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import java.util.ArrayList; +import java.util.List; + import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; +import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.helper.Helper; +import app.fedilab.fedilabtube.sqlite.ManagePlaylistsDAO; +import app.fedilab.fedilabtube.sqlite.Sqlite; import static app.fedilab.fedilabtube.viewmodel.PlaylistsVM.action.GET_LIST_VIDEOS; @@ -69,6 +76,12 @@ public class TimelineVM extends AndroidViewModel { return apiResponseMutableLiveData; } + public LiveData loadVideosInLocalPlaylist(String playlistUuid) { + apiResponseMutableLiveData = new MutableLiveData<>(); + loadVideosInLocalPlayList(playlistUuid); + return apiResponseMutableLiveData; + } + public LiveData getMyVideo(String instance, String videoId) { apiResponseMutableLiveData = new MutableLiveData<>(); getSingle(instance, videoId, true); @@ -144,6 +157,27 @@ public class TimelineVM extends AndroidViewModel { }).start(); } + private void loadVideosInLocalPlayList(String playlistUuid) { + Context _mContext = getApplication().getApplicationContext(); + new Thread(() -> { + try { + SQLiteDatabase db = Sqlite.getInstance(_mContext.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + List videoExports = new ManagePlaylistsDAO(_mContext, db).getAllVideosInPlaylist(playlistUuid); + APIResponse apiResponse = new APIResponse(); + List videos = new ArrayList<>(); + for (VideoData.VideoExport videoExport : videoExports) { + videos.add(videoExport.getVideoData()); + } + apiResponse.setPeertubes(videos); + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse); + mainHandler.post(myRunnable); + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + } + private void loadVideos(TimelineType timeline, String max_id, String forAccount) { Context _mContext = getApplication().getApplicationContext(); new Thread(() -> { @@ -206,6 +240,7 @@ public class TimelineVM extends AndroidViewModel { HISTORY, RECENT, VIDEOS_IN_PLAYLIST, + VIDEOS_IN_LOCAL_PLAYLIST, SEPIA_SEARCH } } diff --git a/app/src/main/res/layout/activity_all_playlist.xml b/app/src/main/res/layout/activity_all_playlist.xml index d00da8c..bef098a 100644 --- a/app/src/main/res/layout/activity_all_playlist.xml +++ b/app/src/main/res/layout/activity_all_playlist.xml @@ -20,7 +20,7 @@ android:paddingLeft="@dimen/fab_margin" android:paddingRight="@dimen/fab_margin"> - -