Allow to export/import
This commit is contained in:
parent
150a81adc6
commit
c3e475be6f
|
@ -18,6 +18,14 @@
|
||||||
<string name="set_video_in_list">Vidéos dans une liste</string>
|
<string name="set_video_in_list">Vidéos dans une liste</string>
|
||||||
<string name="set_video_in_list_description">Change la mise en page pour afficher les vidéos dans une liste</string>
|
<string name="set_video_in_list_description">Change la mise en page pour afficher les vidéos dans une liste</string>
|
||||||
|
|
||||||
|
<string name="export_list">Exporter</string>
|
||||||
|
<string name="import_list">Importer</string>
|
||||||
|
|
||||||
|
<string name="export_notification_title">Exportation réussie !</string>
|
||||||
|
<string name="export_notification_content">Cliquer ici pour envoyer l\'exportation par mèl.</string>
|
||||||
|
<string name="export_notification_subjet">Nouvelle liste de lecture</string>
|
||||||
|
<string name="export_notification_body">Ouvrez la pièce jointe avec l\'application TubeAcad</string>
|
||||||
|
|
||||||
<string name="show_more">Montrer plus</string>
|
<string name="show_more">Montrer plus</string>
|
||||||
<string name="show_less">Montrer moins</string>
|
<string name="show_less">Montrer moins</string>
|
||||||
<string name="no_instances">Aucune instance !</string>
|
<string name="no_instances">Aucune instance !</string>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths>
|
||||||
|
<external-path
|
||||||
|
name="my_images"
|
||||||
|
path="/TubeAcad/" />
|
||||||
|
</paths>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="app.fedilab.fedilabtube">
|
||||||
|
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".FedilabTube"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
|
tools:replace="android:allowBackup">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
tools:node="merge">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:host="*" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
<data android:pathPattern=".*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.tubelab" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</manifest>
|
|
@ -283,6 +283,14 @@
|
||||||
<string name="all">All</string>
|
<string name="all">All</string>
|
||||||
<!-- end languages -->
|
<!-- end languages -->
|
||||||
|
|
||||||
|
|
||||||
|
<string name="export_list">Export</string>
|
||||||
|
<string name="import_list">Import</string>
|
||||||
|
<string name="export_notification_title">Successful export!</string>
|
||||||
|
<string name="export_notification_content">Tap here to send the export by email</string>
|
||||||
|
<string name="export_notification_subjet">New Playlist</string>
|
||||||
|
<string name="export_notification_body">Open the attached file with TubeLab</string>
|
||||||
|
|
||||||
<string name="playlists">Playlists</string>
|
<string name="playlists">Playlists</string>
|
||||||
<string name="display_name">Display name</string>
|
<string name="display_name">Display name</string>
|
||||||
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
|
<string name="action_playlist_add">You don\'t have any playlists. Tap on the \"+\" icon to add a new playlist</string>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<external-path
|
||||||
|
name="my_images"
|
||||||
|
path="/TubeLab/" />
|
||||||
|
|
||||||
|
</paths>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="app.fedilab.fedilabtube">
|
||||||
|
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".FedilabTube"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
|
tools:replace="android:allowBackup">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
tools:node="merge">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:host="*" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
<data android:pathPattern=".*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.tubelab" />
|
||||||
|
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.tubelab" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</manifest>
|
|
@ -161,6 +161,17 @@
|
||||||
android:authorities="${applicationId}.workmanager-init"
|
android:authorities="${applicationId}.workmanager-init"
|
||||||
tools:node="remove"
|
tools:node="remove"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.fileProvider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths" />
|
||||||
|
</provider>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -65,6 +65,7 @@ import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo;
|
||||||
import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment;
|
import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment;
|
||||||
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
|
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
|
||||||
import app.fedilab.fedilabtube.helper.Helper;
|
import app.fedilab.fedilabtube.helper.Helper;
|
||||||
|
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
|
||||||
import app.fedilab.fedilabtube.helper.SwitchAccountHelper;
|
import app.fedilab.fedilabtube.helper.SwitchAccountHelper;
|
||||||
import app.fedilab.fedilabtube.services.RetrieveInfoService;
|
import app.fedilab.fedilabtube.services.RetrieveInfoService;
|
||||||
import app.fedilab.fedilabtube.sqlite.AccountDAO;
|
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 = 5641;
|
||||||
public static int PICK_INSTANCE_SURF = 5642;
|
public static int PICK_INSTANCE_SURF = 5642;
|
||||||
public static UserMe userMe;
|
public static UserMe userMe;
|
||||||
|
public static TypeOfConnection typeOfConnection;
|
||||||
final FragmentManager fm = getSupportFragmentManager();
|
final FragmentManager fm = getSupportFragmentManager();
|
||||||
Fragment active;
|
Fragment active;
|
||||||
private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
|
private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
|
||||||
|
@ -121,7 +123,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public static TypeOfConnection typeOfConnection;
|
|
||||||
|
|
||||||
@SuppressLint("ApplySharedPref")
|
@SuppressLint("ApplySharedPref")
|
||||||
public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) {
|
public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) {
|
||||||
|
@ -359,7 +360,9 @@ public class MainActivity extends AppCompatActivity {
|
||||||
RateThisApp.onCreate(this);
|
RateThisApp.onCreate(this);
|
||||||
RateThisApp.showRateDialogIfNeeded(this);
|
RateThisApp.showRateDialogIfNeeded(this);
|
||||||
}
|
}
|
||||||
|
if (!BuildConfig.full_instances) {
|
||||||
|
PlaylistExportHelper.manageIntentUrl(MainActivity.this, getIntent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startInForeground() {
|
private void startInForeground() {
|
||||||
|
@ -611,9 +614,12 @@ public class MainActivity extends AppCompatActivity {
|
||||||
if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) {
|
if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) {
|
||||||
recreate();
|
recreate();
|
||||||
}
|
}
|
||||||
|
} else if (!BuildConfig.full_instances) {
|
||||||
|
PlaylistExportHelper.manageIntentUrl(MainActivity.this, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("ApplySharedPref")
|
@SuppressLint("ApplySharedPref")
|
||||||
private void showRadioButtonDialog() {
|
private void showRadioButtonDialog() {
|
||||||
|
|
||||||
|
|
|
@ -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,
|
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -24,12 +25,14 @@ import androidx.fragment.app.FragmentTransaction;
|
||||||
import app.fedilab.fedilabtube.client.data.PlaylistData;
|
import app.fedilab.fedilabtube.client.data.PlaylistData;
|
||||||
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
|
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
|
||||||
import app.fedilab.fedilabtube.helper.Helper;
|
import app.fedilab.fedilabtube.helper.Helper;
|
||||||
|
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
|
||||||
import app.fedilab.fedilabtube.viewmodel.TimelineVM;
|
import app.fedilab.fedilabtube.viewmodel.TimelineVM;
|
||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
|
|
||||||
|
|
||||||
public class PlaylistsActivity extends AppCompatActivity {
|
public class PlaylistsActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private final int PICK_IMPORT = 5556;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
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
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
|
|
@ -20,8 +20,6 @@ import android.content.res.ColorStateList;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
|
@ -72,7 +70,6 @@ import app.fedilab.fedilabtube.viewmodel.TimelineVM;
|
||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
|
|
||||||
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY;
|
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.MainActivity.TypeOfConnection.SURFING;
|
||||||
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW;
|
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW;
|
||||||
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE;
|
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE;
|
||||||
|
@ -230,7 +227,7 @@ public class ShowChannelActivity extends AppCompatActivity {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Toasty.error(ShowChannelActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
|
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();
|
Bundle b = new Bundle();
|
||||||
Intent intent = new Intent(ShowChannelActivity.this, ShowAccountActivity.class);
|
Intent intent = new Intent(ShowChannelActivity.this, ShowAccountActivity.class);
|
||||||
b.putParcelable("account", channel.getOwnerAccount());
|
b.putParcelable("account", channel.getOwnerAccount());
|
||||||
|
|
|
@ -755,4 +755,78 @@ public class VideoData {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class VideoExport implements Parcelable {
|
||||||
|
public static final Creator<VideoExport> CREATOR = new Creator<VideoExport>() {
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,15 @@ package app.fedilab.fedilabtube.client.data;
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||||
public class VideoPlaylistData {
|
public class VideoPlaylistData {
|
||||||
|
|
||||||
|
@ -155,4 +159,90 @@ public class VideoPlaylistData {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class VideoPlaylistExport implements Parcelable {
|
||||||
|
|
||||||
|
public static final Creator<VideoPlaylistExport> CREATOR = new Creator<VideoPlaylistExport>() {
|
||||||
|
@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<VideoPlaylistData.VideoPlaylist> 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<VideoPlaylistData.VideoPlaylist> getVideos() {
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVideos(List<VideoPlaylistData.VideoPlaylist> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||||
public class StreamingPlaylists {
|
public class StreamingPlaylists implements Parcelable {
|
||||||
|
|
||||||
|
public static final Creator<StreamingPlaylists> CREATOR = new Creator<StreamingPlaylists>() {
|
||||||
|
@Override
|
||||||
|
public StreamingPlaylists createFromParcel(Parcel in) {
|
||||||
|
return new StreamingPlaylists(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamingPlaylists[] newArray(int size) {
|
||||||
|
return new StreamingPlaylists[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
@SerializedName("id")
|
@SerializedName("id")
|
||||||
private String id;
|
private String id;
|
||||||
@SerializedName("type")
|
@SerializedName("type")
|
||||||
|
@ -34,6 +48,15 @@ public class StreamingPlaylists {
|
||||||
@SerializedName("redundancies")
|
@SerializedName("redundancies")
|
||||||
private List<Redundancies> redundancies;
|
private List<Redundancies> 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() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -82,10 +105,41 @@ public class StreamingPlaylists {
|
||||||
this.redundancies = redundancies;
|
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<Redundancies> CREATOR = new Creator<Redundancies>() {
|
||||||
|
@Override
|
||||||
|
public Redundancies createFromParcel(Parcel in) {
|
||||||
|
return new Redundancies(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Redundancies[] newArray(int size) {
|
||||||
|
return new Redundancies[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
@SerializedName("baseUrl")
|
@SerializedName("baseUrl")
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
|
|
||||||
|
protected Redundancies(Parcel in) {
|
||||||
|
baseUrl = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
public String getBaseUrl() {
|
public String getBaseUrl() {
|
||||||
return baseUrl;
|
return baseUrl;
|
||||||
}
|
}
|
||||||
|
@ -93,5 +147,15 @@ public class StreamingPlaylists {
|
||||||
public void setBaseUrl(String baseUrl) {
|
public void setBaseUrl(String baseUrl) {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
parcel.writeString(baseUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||||
public class ViewsPerDay {
|
public class ViewsPerDay implements Parcelable {
|
||||||
|
|
||||||
|
public static final Creator<ViewsPerDay> CREATOR = new Creator<ViewsPerDay>() {
|
||||||
|
@Override
|
||||||
|
public ViewsPerDay createFromParcel(Parcel in) {
|
||||||
|
return new ViewsPerDay(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewsPerDay[] newArray(int size) {
|
||||||
|
return new ViewsPerDay[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
@SerializedName("date")
|
@SerializedName("date")
|
||||||
private Date date;
|
private Date date;
|
||||||
@SerializedName("views")
|
@SerializedName("views")
|
||||||
private int 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() {
|
public Date getDate() {
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
@ -41,4 +61,15 @@ public class ViewsPerDay {
|
||||||
public void setViews(int views) {
|
public void setViews(int views) {
|
||||||
this.views = 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
@ -37,7 +36,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import app.fedilab.fedilabtube.MainActivity;
|
|
||||||
import app.fedilab.fedilabtube.R;
|
import app.fedilab.fedilabtube.R;
|
||||||
import app.fedilab.fedilabtube.client.data.InstanceData;
|
import app.fedilab.fedilabtube.client.data.InstanceData;
|
||||||
import app.fedilab.fedilabtube.databinding.DrawerAboutInstanceBinding;
|
import app.fedilab.fedilabtube.databinding.DrawerAboutInstanceBinding;
|
||||||
|
|
|
@ -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,
|
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
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.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -29,19 +38,39 @@ import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.appcompat.widget.PopupMenu;
|
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.LifecycleOwner;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.ViewModelStoreOwner;
|
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.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import app.fedilab.fedilabtube.AllPlaylistsActivity;
|
import app.fedilab.fedilabtube.AllPlaylistsActivity;
|
||||||
|
import app.fedilab.fedilabtube.BuildConfig;
|
||||||
|
import app.fedilab.fedilabtube.MainActivity;
|
||||||
import app.fedilab.fedilabtube.PlaylistsActivity;
|
import app.fedilab.fedilabtube.PlaylistsActivity;
|
||||||
import app.fedilab.fedilabtube.R;
|
import app.fedilab.fedilabtube.R;
|
||||||
import app.fedilab.fedilabtube.client.APIResponse;
|
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.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.Helper;
|
||||||
|
import app.fedilab.fedilabtube.helper.NotificationHelper;
|
||||||
|
import app.fedilab.fedilabtube.helper.PlaylistExportHelper;
|
||||||
import app.fedilab.fedilabtube.viewmodel.PlaylistsVM;
|
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 BaseAdapter {
|
||||||
|
@ -122,6 +151,9 @@ public class PlaylistAdapter extends BaseAdapter {
|
||||||
PopupMenu popup = new PopupMenu(context, holder.playlist_more);
|
PopupMenu popup = new PopupMenu(context, holder.playlist_more);
|
||||||
popup.getMenuInflater()
|
popup.getMenuInflater()
|
||||||
.inflate(R.menu.playlist_menu, popup.getMenu());
|
.inflate(R.menu.playlist_menu, popup.getMenu());
|
||||||
|
if (!BuildConfig.full_instances) {
|
||||||
|
popup.getMenu().findItem(R.id.action_export).setVisible(true);
|
||||||
|
}
|
||||||
popup.setOnMenuItemClickListener(item -> {
|
popup.setOnMenuItemClickListener(item -> {
|
||||||
int itemId = item.getItemId();
|
int itemId = item.getItemId();
|
||||||
if (itemId == R.id.action_delete) {
|
if (itemId == R.id.action_delete) {
|
||||||
|
@ -145,6 +177,16 @@ public class PlaylistAdapter extends BaseAdapter {
|
||||||
if (context instanceof AllPlaylistsActivity) {
|
if (context instanceof AllPlaylistsActivity) {
|
||||||
((AllPlaylistsActivity) context).manageAlert(playlist);
|
((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;
|
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<VideoPlaylistData.VideoPlaylist> 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<Bitmap> 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 {
|
private static class ViewHolder {
|
||||||
LinearLayout playlist_container;
|
LinearLayout playlist_container;
|
||||||
ImageView preview_playlist;
|
ImageView preview_playlist;
|
||||||
|
@ -166,5 +272,4 @@ public class PlaylistAdapter extends BaseAdapter {
|
||||||
ImageButton playlist_more;
|
ImageButton playlist_more;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -446,7 +446,6 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void scrollToTop() {
|
public void scrollToTop() {
|
||||||
if (mLayoutManager != null) {
|
if (mLayoutManager != null) {
|
||||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
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<VideoPlaylistData.VideoPlaylistExport>
|
||||||
|
*/
|
||||||
|
public List<VideoPlaylistData.VideoPlaylistExport> 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<VideoData.VideoExport>
|
||||||
|
*/
|
||||||
|
public List<VideoData.VideoExport> 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<VideoPlaylistData.VideoPlaylistExport>
|
||||||
|
*/
|
||||||
|
private List<VideoPlaylistData.VideoPlaylistExport> cursorToVideoPlaylistExport(Cursor c) {
|
||||||
|
//No element found
|
||||||
|
if (c.getCount() == 0) {
|
||||||
|
c.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<VideoPlaylistData.VideoPlaylistExport> 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<VideoData.Video>
|
||||||
|
*/
|
||||||
|
private List<VideoData.VideoExport> cursorToVideoExport(Cursor c) {
|
||||||
|
//No element found
|
||||||
|
if (c.getCount() == 0) {
|
||||||
|
c.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<VideoData.VideoExport> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
public class Sqlite extends 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";
|
public static final String DB_NAME = "mastodon_etalab_db";
|
||||||
/***
|
/***
|
||||||
* List of tables to manage users and data
|
* 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 COL_USER_INSTANCE = "USER_INSTANCE";
|
||||||
static final String TABLE_BOOKMARKED_INSTANCES = "BOOKMARKED_INSTANCES";
|
static final String TABLE_BOOKMARKED_INSTANCES = "BOOKMARKED_INSTANCES";
|
||||||
static final String COL_ABOUT = "ABOUT";
|
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 + " ("
|
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_USER_ID + " TEXT, " + COL_USERNAME + " TEXT NOT NULL, " + COL_ACCT + " TEXT NOT NULL, "
|
||||||
+ COL_DISPLAYED_NAME + " TEXT NOT NULL, " + COL_LOCKED + " INTEGER 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_USER_ID + " TEXT NOT NULL, "
|
||||||
+ COL_ABOUT + " TEXT NOT NULL, "
|
+ COL_ABOUT + " TEXT NOT NULL, "
|
||||||
+ COL_USER_INSTANCE + " 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) {
|
public Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
|
||||||
super(context, name, factory, 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_USER_ACCOUNT);
|
||||||
db.execSQL(CREATE_TABLE_PEERTUBE_FAVOURITES);
|
db.execSQL(CREATE_TABLE_PEERTUBE_FAVOURITES);
|
||||||
db.execSQL(CREATE_TABLE_STORED_INSTANCES);
|
db.execSQL(CREATE_TABLE_STORED_INSTANCES);
|
||||||
|
db.execSQL(CREATE_TABLE_LOCAL_PLAYLISTS);
|
||||||
|
db.execSQL(CREATE_TABLE_VIDEOS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
switch (oldVersion) {
|
switch (oldVersion) {
|
||||||
|
case 3:
|
||||||
|
db.execSQL("DROP TABLE IF EXISTS " + TABLE_VIDEOS);
|
||||||
|
db.execSQL("DROP TABLE IF EXISTS " + TABLE_LOCAL_PLAYLISTS);
|
||||||
case 2:
|
case 2:
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKED_INSTANCES);
|
db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKED_INSTANCES);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +150,9 @@ public class Sqlite extends SQLiteOpenHelper {
|
||||||
switch (oldVersion) {
|
switch (oldVersion) {
|
||||||
case 1:
|
case 1:
|
||||||
db.execSQL(CREATE_TABLE_STORED_INSTANCES);
|
db.execSQL(CREATE_TABLE_STORED_INSTANCES);
|
||||||
|
case 2:
|
||||||
|
db.execSQL(CREATE_TABLE_LOCAL_PLAYLISTS);
|
||||||
|
db.execSQL(CREATE_TABLE_VIDEOS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z" />
|
||||||
|
</vector>
|
|
@ -11,4 +11,10 @@
|
||||||
android:icon="@drawable/ic_baseline_edit_24"
|
android:icon="@drawable/ic_baseline_edit_24"
|
||||||
android:title="@string/edit"
|
android:title="@string/edit"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_export"
|
||||||
|
android:icon="@drawable/ic_baseline_import_export_24"
|
||||||
|
android:title="@string/export_list"
|
||||||
|
android:visible="false"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
Loading…
Reference in New Issue