diff --git a/app/src/acad/res/values/strings.xml b/app/src/acad/res/values/strings.xml
index 17ab7b0..c3612d1 100644
--- a/app/src/acad/res/values/strings.xml
+++ b/app/src/acad/res/values/strings.xml
@@ -18,6 +18,14 @@
Vidéos dans une liste
Change la mise en page pour afficher les vidéos dans une liste
+ Exporter
+ Importer
+
+ Exportation réussie !
+ Cliquer ici pour envoyer l\'exportation par mèl.
+ Nouvelle liste de lecture
+ Ouvrez la pièce jointe avec l\'application TubeAcad
+
Montrer plus
Montrer moins
Aucune instance !
diff --git a/app/src/acad/res/xml/file_paths.xml b/app/src/acad/res/xml/file_paths.xml
new file mode 100644
index 0000000..4175376
--- /dev/null
+++ b/app/src/acad/res/xml/file_paths.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/fdroid_acad/AndroidManifest.xml b/app/src/fdroid_acad/AndroidManifest.xml
new file mode 100644
index 0000000..5b4678e
--- /dev/null
+++ b/app/src/fdroid_acad/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/full/res/values/strings.xml b/app/src/full/res/values/strings.xml
index ab9e427..d34fdfa 100644
--- a/app/src/full/res/values/strings.xml
+++ b/app/src/full/res/values/strings.xml
@@ -283,6 +283,14 @@
All
+
+ Export
+ Import
+ Successful export!
+ Tap here to send the export by email
+ New Playlist
+ Open the attached file with TubeLab
+
Playlists
Display name
You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist
diff --git a/app/src/full/res/xml/file_paths.xml b/app/src/full/res/xml/file_paths.xml
new file mode 100644
index 0000000..2d5ce66
--- /dev/null
+++ b/app/src/full/res/xml/file_paths.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/google_acad/AndroidManifest.xml b/app/src/google_acad/AndroidManifest.xml
new file mode 100644
index 0000000..5b4678e
--- /dev/null
+++ b/app/src/google_acad/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ad808b1..dbad8e1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -161,6 +161,17 @@
android:authorities="${applicationId}.workmanager-init"
tools:node="remove"
android:exported="false" />
+
+
+
+
+
\ 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 73c8462..9c1e99a 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
@@ -65,6 +65,7 @@ import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo;
import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import app.fedilab.fedilabtube.helper.Helper;
+import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
import app.fedilab.fedilabtube.helper.SwitchAccountHelper;
import app.fedilab.fedilabtube.services.RetrieveInfoService;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
@@ -84,6 +85,7 @@ public class MainActivity extends AppCompatActivity {
public static int PICK_INSTANCE = 5641;
public static int PICK_INSTANCE_SURF = 5642;
public static UserMe userMe;
+ public static TypeOfConnection typeOfConnection;
final FragmentManager fm = getSupportFragmentManager();
Fragment active;
private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
@@ -121,7 +123,6 @@ public class MainActivity extends AppCompatActivity {
return false;
}
};
- public static TypeOfConnection typeOfConnection;
@SuppressLint("ApplySharedPref")
public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) {
@@ -359,7 +360,9 @@ public class MainActivity extends AppCompatActivity {
RateThisApp.onCreate(this);
RateThisApp.showRateDialogIfNeeded(this);
}
-
+ if (!BuildConfig.full_instances) {
+ PlaylistExportHelper.manageIntentUrl(MainActivity.this, getIntent());
+ }
}
private void startInForeground() {
@@ -611,9 +614,12 @@ public class MainActivity extends AppCompatActivity {
if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) {
recreate();
}
+ } else if (!BuildConfig.full_instances) {
+ PlaylistExportHelper.manageIntentUrl(MainActivity.this, intent);
}
}
+
@SuppressLint("ApplySharedPref")
private void showRadioButtonDialog() {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/PlaylistsActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PlaylistsActivity.java
index 113bb94..5147f41 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/PlaylistsActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/PlaylistsActivity.java
@@ -14,6 +14,7 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
@@ -24,12 +25,14 @@ 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.helper.PlaylistExportHelper;
import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty;
public class PlaylistsActivity extends AppCompatActivity {
+ private final int PICK_IMPORT = 5556;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -66,6 +69,22 @@ public class PlaylistsActivity extends AppCompatActivity {
}
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == PICK_IMPORT && resultCode == RESULT_OK) {
+ if (data == null || data.getData() == null) {
+ Toasty.error(PlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ return;
+ }
+ PlaylistExportHelper.manageIntentUrl(PlaylistsActivity.this, data);
+
+ } else if (requestCode == PICK_IMPORT) {
+ Toasty.error(PlaylistsActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ }
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
diff --git a/app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java b/app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java
index a01d2c7..faae6f7 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java
@@ -20,8 +20,6 @@ import android.content.res.ColorStateList;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.text.Html;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
@@ -72,7 +70,6 @@ import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY;
-import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.NORMAL;
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.SURFING;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE;
@@ -230,7 +227,7 @@ public class ShowChannelActivity extends AppCompatActivity {
} catch (Exception e) {
Toasty.error(ShowChannelActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
}
- }else if (item.getItemId() == R.id.action_display_account) {
+ } else if (item.getItemId() == R.id.action_display_account) {
Bundle b = new Bundle();
Intent intent = new Intent(ShowChannelActivity.this, ShowAccountActivity.class);
b.putParcelable("account", channel.getOwnerAccount());
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoData.java b/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoData.java
index 3dd0859..2a8676e 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoData.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoData.java
@@ -755,4 +755,78 @@ public class VideoData {
this.description = description;
}
}
+
+
+ public static class VideoExport implements Parcelable {
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public VideoExport createFromParcel(Parcel in) {
+ return new VideoExport(in);
+ }
+
+ @Override
+ public VideoExport[] newArray(int size) {
+ return new VideoExport[size];
+ }
+ };
+ private int id;
+ private String uuid;
+ private Video videoData;
+ private int playlistDBid;
+
+ public VideoExport() {
+ }
+
+ protected VideoExport(Parcel in) {
+ id = in.readInt();
+ uuid = in.readString();
+ videoData = in.readParcelable(Video.class.getClassLoader());
+ playlistDBid = in.readInt();
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public Video getVideoData() {
+ return videoData;
+ }
+
+ public void setVideoData(Video videoData) {
+ this.videoData = videoData;
+ }
+
+ public int getPlaylistDBid() {
+ return playlistDBid;
+ }
+
+ public void setPlaylistDBid(int playlistDBid) {
+ this.playlistDBid = playlistDBid;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeInt(id);
+ parcel.writeString(uuid);
+ parcel.writeParcelable(videoData, i);
+ parcel.writeInt(playlistDBid);
+ }
+ }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoPlaylistData.java b/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoPlaylistData.java
index 4f21e13..9e2db1f 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoPlaylistData.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/data/VideoPlaylistData.java
@@ -15,11 +15,15 @@ package app.fedilab.fedilabtube.client.data;
* see . */
+import android.os.Parcel;
+import android.os.Parcelable;
+
import com.google.gson.annotations.SerializedName;
import java.util.List;
+
@SuppressWarnings({"unused", "RedundantSuppression"})
public class VideoPlaylistData {
@@ -155,4 +159,90 @@ public class VideoPlaylistData {
this.uuid = uuid;
}
}
+
+ public static class VideoPlaylistExport implements Parcelable {
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public VideoPlaylistExport createFromParcel(Parcel in) {
+ return new VideoPlaylistExport(in);
+ }
+
+ @Override
+ public VideoPlaylistExport[] newArray(int size) {
+ return new VideoPlaylistExport[size];
+ }
+ };
+ private long playlistDBkey;
+ private String acct;
+ private String uuid;
+ private PlaylistData.Playlist playlist;
+ private List videos;
+
+
+ public VideoPlaylistExport() {
+ }
+
+ protected VideoPlaylistExport(Parcel in) {
+ playlistDBkey = in.readLong();
+ acct = in.readString();
+ uuid = in.readString();
+ playlist = in.readParcelable(PlaylistData.Playlist.class.getClassLoader());
+ in.readList(this.videos, VideoPlaylistData.VideoPlaylist.class.getClassLoader());
+ }
+
+ public String getAcct() {
+ return acct;
+ }
+
+ public void setAcct(String acct) {
+ this.acct = acct;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public PlaylistData.Playlist getPlaylist() {
+ return playlist;
+ }
+
+ public void setPlaylist(PlaylistData.Playlist playlist) {
+ this.playlist = playlist;
+ }
+
+ public long getPlaylistDBkey() {
+ return playlistDBkey;
+ }
+
+ public void setPlaylistDBkey(long playlistDBkey) {
+ this.playlistDBkey = playlistDBkey;
+ }
+
+ public List getVideos() {
+ return videos;
+ }
+
+ public void setVideos(List videos) {
+ this.videos = videos;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeLong(playlistDBkey);
+ parcel.writeString(acct);
+ parcel.writeString(uuid);
+ parcel.writeParcelable(playlist, i);
+ parcel.writeList(videos);
+ }
+ }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/StreamingPlaylists.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/StreamingPlaylists.java
index f3ea3e2..dca4c6d 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/entities/StreamingPlaylists.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/StreamingPlaylists.java
@@ -14,13 +14,27 @@ package app.fedilab.fedilabtube.client.entities;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.os.Parcel;
+import android.os.Parcelable;
+
import com.google.gson.annotations.SerializedName;
import java.util.List;
@SuppressWarnings({"unused", "RedundantSuppression"})
-public class StreamingPlaylists {
+public class StreamingPlaylists implements Parcelable {
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public StreamingPlaylists createFromParcel(Parcel in) {
+ return new StreamingPlaylists(in);
+ }
+
+ @Override
+ public StreamingPlaylists[] newArray(int size) {
+ return new StreamingPlaylists[size];
+ }
+ };
@SerializedName("id")
private String id;
@SerializedName("type")
@@ -34,6 +48,15 @@ public class StreamingPlaylists {
@SerializedName("redundancies")
private List redundancies;
+ protected StreamingPlaylists(Parcel in) {
+ id = in.readString();
+ type = in.readInt();
+ playlistUrl = in.readString();
+ segmentsSha256Url = in.readString();
+ files = in.createTypedArrayList(File.CREATOR);
+ redundancies = in.createTypedArrayList(Redundancies.CREATOR);
+ }
+
public String getId() {
return id;
}
@@ -82,10 +105,41 @@ public class StreamingPlaylists {
this.redundancies = redundancies;
}
- public static class Redundancies {
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(id);
+ parcel.writeInt(type);
+ parcel.writeString(playlistUrl);
+ parcel.writeString(segmentsSha256Url);
+ parcel.writeTypedList(files);
+ parcel.writeTypedList(redundancies);
+ }
+
+
+ public static class Redundancies implements Parcelable {
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public Redundancies createFromParcel(Parcel in) {
+ return new Redundancies(in);
+ }
+
+ @Override
+ public Redundancies[] newArray(int size) {
+ return new Redundancies[size];
+ }
+ };
@SerializedName("baseUrl")
private String baseUrl;
+ protected Redundancies(Parcel in) {
+ baseUrl = in.readString();
+ }
+
public String getBaseUrl() {
return baseUrl;
}
@@ -93,5 +147,15 @@ public class StreamingPlaylists {
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(baseUrl);
+ }
}
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/ViewsPerDay.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/ViewsPerDay.java
index d1c372c..cba2d80 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/client/entities/ViewsPerDay.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/ViewsPerDay.java
@@ -14,18 +14,38 @@ package app.fedilab.fedilabtube.client.entities;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see . */
+import android.os.Parcel;
+import android.os.Parcelable;
+
import com.google.gson.annotations.SerializedName;
import java.util.Date;
@SuppressWarnings({"unused", "RedundantSuppression"})
-public class ViewsPerDay {
+public class ViewsPerDay implements Parcelable {
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public ViewsPerDay createFromParcel(Parcel in) {
+ return new ViewsPerDay(in);
+ }
+
+ @Override
+ public ViewsPerDay[] newArray(int size) {
+ return new ViewsPerDay[size];
+ }
+ };
@SerializedName("date")
private Date date;
@SerializedName("views")
private int views;
+ protected ViewsPerDay(Parcel in) {
+ long tmpDate = in.readLong();
+ this.date = tmpDate == -1 ? null : new Date(tmpDate);
+ views = in.readInt();
+ }
+
public Date getDate() {
return date;
}
@@ -41,4 +61,15 @@ public class ViewsPerDay {
public void setViews(int views) {
this.views = views;
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeLong(this.date != null ? this.date.getTime() : -1);
+ parcel.writeInt(views);
+ }
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/AboutInstanceAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/AboutInstanceAdapter.java
index c6f5acf..b918bc1 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/drawer/AboutInstanceAdapter.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/AboutInstanceAdapter.java
@@ -19,7 +19,6 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
@@ -37,7 +36,6 @@ import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
-import app.fedilab.fedilabtube.MainActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.InstanceData;
import app.fedilab.fedilabtube.databinding.DrawerAboutInstanceBinding;
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 a1aa6c9..d697dd2 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/drawer/PlaylistAdapter.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/PlaylistAdapter.java
@@ -14,10 +14,19 @@ 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.Manifest;
+import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -29,19 +38,39 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.widget.PopupMenu;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.core.content.FileProvider;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.FutureTarget;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import app.fedilab.fedilabtube.AllPlaylistsActivity;
+import app.fedilab.fedilabtube.BuildConfig;
+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.helper.Helper;
+import app.fedilab.fedilabtube.helper.NotificationHelper;
+import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
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 {
@@ -122,6 +151,9 @@ public class PlaylistAdapter extends BaseAdapter {
PopupMenu popup = new PopupMenu(context, holder.playlist_more);
popup.getMenuInflater()
.inflate(R.menu.playlist_menu, popup.getMenu());
+ if (!BuildConfig.full_instances) {
+ popup.getMenu().findItem(R.id.action_export).setVisible(true);
+ }
popup.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.action_delete) {
@@ -145,6 +177,16 @@ public class PlaylistAdapter extends BaseAdapter {
if (context instanceof AllPlaylistsActivity) {
((AllPlaylistsActivity) context).manageAlert(playlist);
}
+ } else if (itemId == R.id.action_export) {
+ if (Build.VERSION.SDK_INT >= 23) {
+ if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
+ } else {
+ doExport(playlist);
+ }
+ } else {
+ doExport(playlist);
+ }
}
return true;
});
@@ -159,6 +201,70 @@ public class PlaylistAdapter extends BaseAdapter {
}
+ private void doExport(Playlist playlist) {
+ new Thread(() -> {
+ File file = null;
+ RetrofitPeertubeAPI retrofitPeertubeAPI = new RetrofitPeertubeAPI(context);
+ APIResponse apiResponse = retrofitPeertubeAPI.playlistAction(GET_LIST_VIDEOS, playlist.getId(), null, null, null);
+ if (apiResponse != null) {
+ List videos = apiResponse.getVideoPlaylist();
+ VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = new VideoPlaylistData.VideoPlaylistExport();
+ videoPlaylistExport.setPlaylist(playlist);
+ videoPlaylistExport.setUuid(playlist.getUuid());
+ videoPlaylistExport.setAcct(MainActivity.userMe.getAccount().getAcct());
+ videoPlaylistExport.setVideos(videos);
+
+ String data = PlaylistExportHelper.playlistToStringStorage(videoPlaylistExport);
+
+
+ File root = new File(Environment.getExternalStorageDirectory(), context.getString(R.string.app_name));
+ if (!root.exists()) {
+ root.mkdirs();
+ }
+ file = new File(root, "playlist_" + playlist.getUuid() + ".tubelab");
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(file);
+ writer.append(data);
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> Toasty.error(context, context.getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
+ mainHandler.post(myRunnable);
+ return;
+ }
+
+
+ }
+ String urlAvatar = playlist.getThumbnailPath() != null ? Helper.getLiveInstance(context) + playlist.getThumbnailPath() : null;
+ FutureTarget futureBitmapChannel = Glide.with(context.getApplicationContext())
+ .asBitmap()
+ .load(urlAvatar != null ? urlAvatar : R.drawable.missing_peertube).submit();
+ Bitmap icon = null;
+ try {
+ icon = futureBitmapChannel.get();
+ } catch (ExecutionException | InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (file != null) {
+ Intent mailIntent = new Intent(Intent.ACTION_SEND);
+ mailIntent.setType("message/rfc822");
+ Uri contentUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileProvider", file);
+ mailIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.export_notification_subjet));
+ mailIntent.putExtra(Intent.EXTRA_TEXT, context.getString(R.string.export_notification_body));
+ mailIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
+ NotificationHelper.notify_user(context.getApplicationContext(),
+ playlist.getOwnerAccount(), mailIntent, icon,
+ context.getString(R.string.export_notification_title),
+ context.getString(R.string.export_notification_content));
+ }
+
+
+ }).start();
+ }
+
private static class ViewHolder {
LinearLayout playlist_container;
ImageView preview_playlist;
@@ -166,5 +272,4 @@ public class PlaylistAdapter extends BaseAdapter {
ImageButton playlist_more;
}
-
}
\ No newline at end of file
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 a46a950..dde9739 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java
@@ -446,7 +446,6 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
}
-
public void scrollToTop() {
if (mLayoutManager != null) {
mLayoutManager.scrollToPositionWithOffset(0, 0);
diff --git a/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java b/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java
new file mode 100644
index 0000000..d57b3d7
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/helper/PlaylistExportHelper.java
@@ -0,0 +1,105 @@
+package app.fedilab.fedilabtube.helper;
+/* Copyright 2020 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+import android.app.Activity;
+import android.content.Intent;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.google.gson.Gson;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import app.fedilab.fedilabtube.PlaylistsActivity;
+import app.fedilab.fedilabtube.client.data.VideoPlaylistData;
+import app.fedilab.fedilabtube.sqlite.ManagePlaylistsDAO;
+import app.fedilab.fedilabtube.sqlite.Sqlite;
+
+public class PlaylistExportHelper {
+
+
+ /**
+ * Unserialized VideoPlaylistExport
+ *
+ * @param serializedVideoPlaylistExport String serialized VideoPlaylistExport
+ * @return VideoPlaylistExport
+ */
+ public static VideoPlaylistData.VideoPlaylistExport restorePlaylistFromString(String serializedVideoPlaylistExport) {
+ Gson gson = new Gson();
+ try {
+ return gson.fromJson(serializedVideoPlaylistExport, VideoPlaylistData.VideoPlaylistExport.class);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Serialized VideoPlaylistExport class
+ *
+ * @param videoPlaylistExport Playlist to serialize
+ * @return String serialized VideoPlaylistData.VideoPlaylistExport
+ */
+ public static String playlistToStringStorage(VideoPlaylistData.VideoPlaylistExport videoPlaylistExport) {
+ Gson gson = new Gson();
+ try {
+ return gson.toJson(videoPlaylistExport);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Manage intent for opening a tubelab file allowing to import a whole playlist and store it in db
+ *
+ * @param activity Activity
+ * @param intent Intent
+ */
+ public static void manageIntentUrl(Activity activity, Intent intent) {
+ if (intent.getData() != null) {
+ String url = intent.getData().toString();
+ if (url.endsWith(".json")) {
+ File file = new File(url);
+ StringBuilder text = new StringBuilder();
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(file));
+ String line;
+ while ((line = br.readLine()) != null) {
+ text.append(line);
+ text.append('\n');
+ }
+ br.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if (text.length() > 20) {
+ new Thread(() -> {
+ VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = PlaylistExportHelper.restorePlaylistFromString(text.toString());
+ if (videoPlaylistExport != null) {
+ SQLiteDatabase db = Sqlite.getInstance(activity.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ new ManagePlaylistsDAO(activity, db).insertPlaylist(videoPlaylistExport);
+ }
+ activity.runOnUiThread(() -> {
+ Intent intentPlaylist = new Intent(activity, PlaylistsActivity.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
new file mode 100644
index 0000000..b5d99b4
--- /dev/null
+++ b/app/src/main/java/app/fedilab/fedilabtube/sqlite/ManagePlaylistsDAO.java
@@ -0,0 +1,344 @@
+package app.fedilab.fedilabtube.sqlite;
+/* 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.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.google.gson.Gson;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import app.fedilab.fedilabtube.client.data.PlaylistData;
+import app.fedilab.fedilabtube.client.data.VideoData;
+import app.fedilab.fedilabtube.client.data.VideoPlaylistData;
+
+
+@SuppressWarnings("UnusedReturnValue")
+public class ManagePlaylistsDAO {
+
+ private final SQLiteDatabase db;
+ public Context context;
+
+
+ public ManagePlaylistsDAO(Context context, SQLiteDatabase db) {
+ //Creation of the DB with tables
+ this.context = context;
+ this.db = db;
+ }
+
+ /**
+ * Unserialized Video
+ *
+ * @param serializedVideo String serialized Video
+ * @return Video
+ */
+ public static VideoData.Video restoreVideoFromString(String serializedVideo) {
+ Gson gson = new Gson();
+ try {
+ return gson.fromJson(serializedVideo, VideoData.Video.class);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Serialized Video class
+ *
+ * @param video Video to serialize
+ * @return String serialized video
+ */
+ public static String videoToStringStorage(VideoData.Video video) {
+ Gson gson = new Gson();
+ try {
+ return gson.toJson(video);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Unserialized Playlist
+ *
+ * @param serializedPlaylist String serialized Playlist
+ * @return Playlist
+ */
+ public static PlaylistData.Playlist restorePlaylistFromString(String serializedPlaylist) {
+ Gson gson = new Gson();
+ try {
+ return gson.fromJson(serializedPlaylist, PlaylistData.Playlist.class);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Serialized Playlist class
+ *
+ * @param playlist Playlist to serialize
+ * @return String serialized playlist
+ */
+ public static String playlistToStringStorage(PlaylistData.Playlist playlist) {
+ Gson gson = new Gson();
+ try {
+ return gson.toJson(playlist);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Insert playlist info in database
+ *
+ * @param videoPlaylistExport VideoPlaylistExport
+ * @return boolean
+ */
+ public boolean insertPlaylist(VideoPlaylistData.VideoPlaylistExport videoPlaylistExport) {
+
+ if (videoPlaylistExport.getPlaylist() == null || checkExists(videoPlaylistExport.getPlaylist().getUuid())) {
+ return true;
+ }
+ ContentValues values = new ContentValues();
+ values.put(Sqlite.COL_ACCT, videoPlaylistExport.getAcct());
+ values.put(Sqlite.COL_UUID, videoPlaylistExport.getUuid());
+ 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);
+ for (VideoPlaylistData.VideoPlaylist videoPlaylist : videoPlaylistExport.getVideos()) {
+ //Insert videos
+ insertVideos(videoPlaylist.getVideo(), videoPlaylistExport);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Insert videos for playlists in database
+ *
+ * @param video Video to insert
+ * @param playlist VideoPlaylistExport targeted
+ * @return boolean
+ */
+ private boolean insertVideos(VideoData.Video video, VideoPlaylistData.VideoPlaylistExport playlist) {
+
+ if (video == null || playlist == null || checkVideoExists(video.getUuid(), playlist.getUuid())) {
+ return true;
+ }
+ ContentValues values = new ContentValues();
+ values.put(Sqlite.COL_UUID, video.getUuid());
+ values.put(Sqlite.COL_PLAYLIST_ID, playlist.getPlaylistDBkey());
+ values.put(Sqlite.COL_VIDEO_DATA, videoToStringStorage(video));
+ //Inserts playlist
+ try {
+ db.insertOrThrow(Sqlite.TABLE_VIDEOS, null, values);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if playlist exists
+ *
+ * @param uuid String
+ * @return int
+ */
+ private boolean 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();
+ c.close();
+ return count > 0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ }
+
+ /**
+ * Check if playlist exists
+ *
+ * @param videoUuid String
+ * @param playlistUuid String
+ * @return int
+ */
+ private boolean checkVideoExists(String videoUuid, String playlistUuid) {
+ try {
+ String check_query = "SELECT * FROM " + Sqlite.TABLE_LOCAL_PLAYLISTS + " p INNER JOIN "
+ + Sqlite.TABLE_VIDEOS + " v ON p.id = v." + Sqlite.COL_PLAYLIST_ID
+ + " WHERE p." + Sqlite.COL_UUID + "=? AND v." + Sqlite.COL_UUID + "=? LIMIT 1";
+ Cursor c = db.rawQuery(check_query, new String[]{playlistUuid, videoUuid});
+ int count = c.getCount();
+ c.close();
+ return count > 0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ }
+
+
+ /**
+ * Remove a playlist with its uuid
+ *
+ * @param uuid String uuid of the Playlist
+ * @return int
+ */
+ public int removePlaylist(String uuid) {
+ VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = getSinglePlaylists(uuid);
+ db.delete(Sqlite.TABLE_VIDEOS, Sqlite.COL_PLAYLIST_ID + " = '" + videoPlaylistExport.getPlaylistDBkey() + "'", null);
+ return db.delete(Sqlite.TABLE_LOCAL_PLAYLISTS, Sqlite.COL_ID + " = '" + videoPlaylistExport.getPlaylistDBkey() + "'", null);
+ }
+
+
+ /**
+ * Returns a playlist from it's uid in db
+ *
+ * @return VideoPlaylistExport
+ */
+ public VideoPlaylistData.VideoPlaylistExport getSinglePlaylists(String uuid) {
+
+ try {
+ Cursor c = db.query(Sqlite.TABLE_LOCAL_PLAYLISTS, null, Sqlite.COL_UUID + "='" + uuid + "'", null, null, null, Sqlite.COL_ID + " DESC", null);
+ return cursorToSingleVideoPlaylistExport(c);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ /**
+ * Returns all playlists in db
+ *
+ * @return List
+ */
+ public List getAllPlaylists() {
+
+ try {
+ Cursor c = db.query(Sqlite.TABLE_LOCAL_PLAYLISTS, null, null, null, null, null, Sqlite.COL_ID + " DESC", null);
+ return cursorToVideoPlaylistExport(c);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ /**
+ * Returns all videos in a playlist
+ *
+ * @return List
+ */
+ public List getAllVideosInPlaylist(VideoPlaylistData.VideoPlaylistExport videoPlaylistExport) {
+
+ try {
+ 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
+ * @param c Cursor
+ * @return VideoPlaylistData.VideoPlaylistExport
+ */
+ private VideoPlaylistData.VideoPlaylistExport cursorToSingleVideoPlaylistExport(Cursor c) {
+ //No element found
+ if (c.getCount() == 0) {
+ c.close();
+ return null;
+ }
+ c.moveToFirst();
+ VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = new VideoPlaylistData.VideoPlaylistExport();
+ videoPlaylistExport.setAcct(c.getString(c.getColumnIndex(Sqlite.COL_ACCT)));
+ videoPlaylistExport.setUuid(c.getString(c.getColumnIndex(Sqlite.COL_UUID)));
+ videoPlaylistExport.setPlaylistDBkey(c.getInt(c.getColumnIndex(Sqlite.COL_ID)));
+ videoPlaylistExport.setPlaylist(restorePlaylistFromString(c.getString(c.getColumnIndex(Sqlite.COL_PLAYLIST))));
+ //Close the cursor
+ c.close();
+ return videoPlaylistExport;
+ }
+
+
+ /***
+ * Method to hydrate VideoPlaylistExport from database
+ * @param c Cursor
+ * @return List
+ */
+ private List cursorToVideoPlaylistExport(Cursor c) {
+ //No element found
+ if (c.getCount() == 0) {
+ c.close();
+ return null;
+ }
+ List videoPlaylistExports = new ArrayList<>();
+ while (c.moveToNext()) {
+ VideoPlaylistData.VideoPlaylistExport videoPlaylistExport = new VideoPlaylistData.VideoPlaylistExport();
+ videoPlaylistExport.setAcct(c.getString(c.getColumnIndex(Sqlite.COL_ACCT)));
+ videoPlaylistExport.setUuid(c.getString(c.getColumnIndex(Sqlite.COL_UUID)));
+ videoPlaylistExport.setPlaylistDBkey(c.getInt(c.getColumnIndex(Sqlite.COL_ID)));
+ videoPlaylistExport.setPlaylist(restorePlaylistFromString(c.getString(c.getColumnIndex(Sqlite.COL_PLAYLIST))));
+ videoPlaylistExports.add(videoPlaylistExport);
+ }
+ //Close the cursor
+ c.close();
+ return videoPlaylistExports;
+ }
+
+
+ /***
+ * Method to hydrate Video from database
+ * @param c Cursor
+ * @return List
+ */
+ private List cursorToVideoExport(Cursor c) {
+ //No element found
+ if (c.getCount() == 0) {
+ c.close();
+ return null;
+ }
+ List videoExports = new ArrayList<>();
+ while (c.moveToNext()) {
+ VideoData.VideoExport videoExport = new VideoData.VideoExport();
+ videoExport.setPlaylistDBid(c.getInt(c.getColumnIndex(Sqlite.COL_PLAYLIST_ID)));
+ videoExport.setUuid(c.getString(c.getColumnIndex(Sqlite.COL_UUID)));
+ videoExport.setId(c.getInt(c.getColumnIndex(Sqlite.COL_ID)));
+ videoExport.setVideoData(restoreVideoFromString(c.getString(c.getColumnIndex(Sqlite.COL_VIDEO_DATA))));
+ videoExports.add(videoExport);
+ }
+ //Close the cursor
+ c.close();
+ return videoExports;
+ }
+
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java b/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java
index 6f41ca6..5503449 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java
@@ -21,7 +21,7 @@ import android.database.sqlite.SQLiteOpenHelper;
public class Sqlite extends SQLiteOpenHelper {
- public static final int DB_VERSION = 2;
+ public static final int DB_VERSION = 3;
public static final String DB_NAME = "mastodon_etalab_db";
/***
* List of tables to manage users and data
@@ -62,6 +62,11 @@ public class Sqlite extends SQLiteOpenHelper {
static final String COL_USER_INSTANCE = "USER_INSTANCE";
static final String TABLE_BOOKMARKED_INSTANCES = "BOOKMARKED_INSTANCES";
static final String COL_ABOUT = "ABOUT";
+ static final String TABLE_LOCAL_PLAYLISTS = "LOCAL_PLAYLISTS";
+ static final String COL_PLAYLIST = "PLAYLIST";
+ static final String TABLE_VIDEOS = "VIDEOS";
+ static final String COL_VIDEO_DATA = "VIDEO_DATA";
+ static final String COL_PLAYLIST_ID = "PLAYLIST_ID";
private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " ("
+ COL_USER_ID + " TEXT, " + COL_USERNAME + " TEXT NOT NULL, " + COL_ACCT + " TEXT NOT NULL, "
+ COL_DISPLAYED_NAME + " TEXT NOT NULL, " + COL_LOCKED + " INTEGER NOT NULL, "
@@ -92,6 +97,19 @@ public class Sqlite extends SQLiteOpenHelper {
+ COL_USER_ID + " TEXT NOT NULL, "
+ COL_ABOUT + " TEXT NOT NULL, "
+ COL_USER_INSTANCE + " TEXT NOT NULL)";
+ private final String CREATE_TABLE_LOCAL_PLAYLISTS = "CREATE TABLE "
+ + TABLE_LOCAL_PLAYLISTS + "("
+ + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ + COL_ACCT + " TEXT NOT NULL, "
+ + COL_UUID + " TEXT NOT NULL, "
+ + COL_PLAYLIST + " TEXT NOT NULL)";
+ private final String CREATE_TABLE_VIDEOS = "CREATE TABLE "
+ + TABLE_VIDEOS + "("
+ + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ + COL_UUID + " TEXT NOT NULL, "
+ + COL_VIDEO_DATA + " TEXT NOT NULL, "
+ + COL_PLAYLIST_ID + " INTEGER, "
+ + " FOREIGN KEY (" + COL_PLAYLIST_ID + ") REFERENCES " + COL_PLAYLIST + "(" + COL_ID + "));";
public Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
@@ -111,13 +129,19 @@ public class Sqlite extends SQLiteOpenHelper {
db.execSQL(CREATE_TABLE_USER_ACCOUNT);
db.execSQL(CREATE_TABLE_PEERTUBE_FAVOURITES);
db.execSQL(CREATE_TABLE_STORED_INSTANCES);
+ db.execSQL(CREATE_TABLE_LOCAL_PLAYLISTS);
+ db.execSQL(CREATE_TABLE_VIDEOS);
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
+ case 3:
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_VIDEOS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_LOCAL_PLAYLISTS);
case 2:
db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKED_INSTANCES);
+
}
}
@@ -126,6 +150,9 @@ public class Sqlite extends SQLiteOpenHelper {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_TABLE_STORED_INSTANCES);
+ case 2:
+ db.execSQL(CREATE_TABLE_LOCAL_PLAYLISTS);
+ db.execSQL(CREATE_TABLE_VIDEOS);
}
}
diff --git a/app/src/main/res/drawable/ic_baseline_import_export_24.xml b/app/src/main/res/drawable/ic_baseline_import_export_24.xml
new file mode 100644
index 0000000..2418755
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_import_export_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/menu/playlist_menu.xml b/app/src/main/res/menu/playlist_menu.xml
index f9da37c..fd9e0f1 100644
--- a/app/src/main/res/menu/playlist_menu.xml
+++ b/app/src/main/res/menu/playlist_menu.xml
@@ -11,4 +11,10 @@
android:icon="@drawable/ic_baseline_edit_24"
android:title="@string/edit"
app:showAsAction="ifRoom" />
+