turned more files to kotlin
This commit is contained in:
parent
92d6b2f197
commit
6dc413cbd2
28 changed files with 578 additions and 855 deletions
|
|
@ -320,7 +320,7 @@
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="url" value="jar:file:/C:/Program%20Files/Android/Android%20Studio/plugins/android/lib/android.jar!/images/material/icons/materialicons/history/baseline_history_24.xml" />
|
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/drag_handle/baseline_drag_handle_24.xml" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
|
|
@ -330,7 +330,7 @@
|
||||||
</option>
|
</option>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="outputName" value="ic_history" />
|
<entry key="outputName" value="ic_handle" />
|
||||||
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
|
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
|
|
|
||||||
|
|
@ -1,351 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.database;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.database.models.HistoryItem;
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class DatabaseManager extends SQLiteOpenHelper {
|
|
||||||
Context context;
|
|
||||||
|
|
||||||
public static final String db_name = "ytdlnis_db";
|
|
||||||
public static final int db_version = 7;
|
|
||||||
public static final String results_table_name = "results";
|
|
||||||
public static final String history_table_name = "history";
|
|
||||||
public static final String id = "id";
|
|
||||||
public static final String videoId = "videoId";
|
|
||||||
public static final String url = "url";
|
|
||||||
public static final String title = "title";
|
|
||||||
public static final String author = "author";
|
|
||||||
public static final String duration = "duration";
|
|
||||||
public static final String thumb = "thumb";
|
|
||||||
public static final String downloadedAudio = "downloadedAudio";
|
|
||||||
public static final String downloadedVideo = "downloadedVideo";
|
|
||||||
public static final String type = "type";
|
|
||||||
public static final String time = "time";
|
|
||||||
public static final String isPlaylistItem = "isPlaylistItem";
|
|
||||||
public static final String website = "website";
|
|
||||||
public static final String downloadPath = "downloadPath";
|
|
||||||
public static final String downloadingAudio = "downloadingAudio";
|
|
||||||
public static final String downloadingVideo = "downloadingVideo";
|
|
||||||
public static final String playlistTitle = "playlistTitle";
|
|
||||||
public static final String isQueuedDownload = "isQueuedDownload";
|
|
||||||
|
|
||||||
public DatabaseManager(Context context){
|
|
||||||
super(context, db_name, null, db_version);
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(SQLiteDatabase sqLiteDatabase) {
|
|
||||||
String query = "CREATE TABLE " + results_table_name + " ("
|
|
||||||
+ id + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
||||||
+ videoId + " TEXT,"
|
|
||||||
+ url + " TEXT,"
|
|
||||||
+ title + " TEXT,"
|
|
||||||
+ author + " TEXT,"
|
|
||||||
+ duration + " TEXT,"
|
|
||||||
+ thumb + " TEXT,"
|
|
||||||
+ downloadedAudio + " INTEGER,"
|
|
||||||
+ downloadedVideo + " INTEGER,"
|
|
||||||
+ isPlaylistItem + " INTENGER,"
|
|
||||||
+ website + " TEXT,"
|
|
||||||
+ downloadingAudio + " INTEGER,"
|
|
||||||
+ downloadingVideo + " INTEGER,"
|
|
||||||
+ playlistTitle + " TEXT)";
|
|
||||||
|
|
||||||
sqLiteDatabase.execSQL(query);
|
|
||||||
|
|
||||||
query = "CREATE TABLE " + history_table_name + " ("
|
|
||||||
+ id + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
||||||
+ url + " TEXT,"
|
|
||||||
+ title + " TEXT,"
|
|
||||||
+ author + " TEXT,"
|
|
||||||
+ duration + " TEXT,"
|
|
||||||
+ thumb + " TEXT,"
|
|
||||||
+ type + " TEXT,"
|
|
||||||
+ time + " TEXT,"
|
|
||||||
+ downloadPath + " TEXT,"
|
|
||||||
+ website + " TEXT,"
|
|
||||||
+ isQueuedDownload + " INTEGER)";
|
|
||||||
|
|
||||||
sqLiteDatabase.execSQL(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearHistory(){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
db.execSQL("DELETE FROM " + history_table_name);
|
|
||||||
|
|
||||||
//remove downloaded statuses from results
|
|
||||||
db.execSQL("UPDATE "+results_table_name+ " SET downloadedAudio=0, downloadedVideo=0" +
|
|
||||||
" WHERE downloadedAudio=1 OR downloadedVideo=1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("Range")
|
|
||||||
public void clearHistoryItem(HistoryItem video, boolean delete_file){
|
|
||||||
// SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
//
|
|
||||||
// if (delete_file){
|
|
||||||
// try{
|
|
||||||
// Cursor cursor = db.rawQuery("SELECT * FROM " + history_table_name + " WHERE url='" +
|
|
||||||
// video.getURL() + "' AND type='"+video.getDownloadedType() + "' LIMIT 1", null);
|
|
||||||
//
|
|
||||||
// if(cursor.moveToFirst()){
|
|
||||||
// String path = cursor.getString(cursor.getColumnIndex(downloadPath));
|
|
||||||
// File file = new File(path);
|
|
||||||
// if(file.exists()){
|
|
||||||
// file.delete();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }catch (Exception e){
|
|
||||||
// Toast.makeText(context, R.string.error_deleting_file, Toast.LENGTH_SHORT).show();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// db.execSQL("DELETE FROM " + history_table_name + " WHERE id=" + video.getId());
|
|
||||||
//
|
|
||||||
// String where = "";
|
|
||||||
// switch(video.getDownloadedType()){
|
|
||||||
// case "audio":
|
|
||||||
// where = " SET downloadedAudio=0 WHERE downloadedAudio=1 AND videoId='" + video.getVideoId()+"'";
|
|
||||||
// break;
|
|
||||||
// case "video":
|
|
||||||
// where = " SET downloadedVideo=0 WHERE downloadedVideo=1 AND videoId='" + video.getVideoId()+"'";
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //remove downloaded status from results
|
|
||||||
// db.execSQL("UPDATE "+results_table_name+ where);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearDeletedHistory(){
|
|
||||||
// ArrayList<ResultItem> videos = getHistory("","","","");
|
|
||||||
// for (int i = 0; i < videos.size(); i++){
|
|
||||||
// ResultItem video = videos.get(i);
|
|
||||||
// String path = video.getDownloadPath();
|
|
||||||
// File file = new File(path);
|
|
||||||
// if(!file.exists() && !path.isEmpty()){
|
|
||||||
// clearHistoryItem(video, false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearDownloadingHistory(){
|
|
||||||
// ArrayList<ResultItem> videos = getHistory("","","","");
|
|
||||||
// for (int i = 0; i < videos.size(); i++){
|
|
||||||
// ResultItem video = videos.get(i);
|
|
||||||
// if(video.isQueuedDownload()){
|
|
||||||
// clearHistoryItem(video, false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearDuplicateHistory(){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
db.execSQL(
|
|
||||||
"DELETE FROM " + history_table_name +
|
|
||||||
" WHERE id > (SELECT MIN(h.id) FROM history h WHERE h.url = " + history_table_name + ".url" +
|
|
||||||
" AND h.type = " + history_table_name + ".type);"
|
|
||||||
);
|
|
||||||
|
|
||||||
//remove downloaded statuses from results
|
|
||||||
db.execSQL("UPDATE "+results_table_name+ " SET downloadedAudio=0, downloadedVideo=0" +
|
|
||||||
" WHERE downloadedAudio=1 OR downloadedVideo=1");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearResults(){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
db.execSQL("DELETE FROM " + results_table_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVer, int newVer) {
|
|
||||||
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + results_table_name);
|
|
||||||
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + history_table_name);
|
|
||||||
onCreate(sqLiteDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("Range")
|
|
||||||
public ArrayList<ResultItem> getResults(){
|
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
|
||||||
Cursor cursor = db.rawQuery("SELECT * FROM " + results_table_name, null);
|
|
||||||
ArrayList<ResultItem> list = new ArrayList<>();
|
|
||||||
|
|
||||||
// if(cursor.moveToFirst()){
|
|
||||||
// do {
|
|
||||||
// // on below line we are adding the data from cursor to our array list.
|
|
||||||
// list.add(new ResultItem(cursor.getString(cursor.getColumnIndex(videoId)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(url)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(title)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(author)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(duration)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(thumb)),
|
|
||||||
// cursor.getInt(cursor.getColumnIndex(downloadedAudio)),
|
|
||||||
// cursor.getInt(cursor.getColumnIndex(downloadedVideo)),
|
|
||||||
// cursor.getInt(cursor.getColumnIndex(isPlaylistItem)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(website)),
|
|
||||||
// cursor.getInt(cursor.getColumnIndex(downloadedAudio)),
|
|
||||||
// cursor.getInt(cursor.getColumnIndex(downloadingVideo)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(playlistTitle))));
|
|
||||||
// } while (cursor.moveToNext());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cursor.close();
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("Range")
|
|
||||||
public ArrayList<ResultItem> getHistory(String query, String format, String site, String sort){
|
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
|
||||||
|
|
||||||
if (sort == null || sort.isEmpty()) sort = "DESC";
|
|
||||||
Cursor cursor = db.rawQuery("SELECT * FROM " + history_table_name
|
|
||||||
+ " WHERE title LIKE '%"+query+"%'"+
|
|
||||||
" AND type LIKE '%"+format+"%'"+
|
|
||||||
" AND website LIKE '%"+site+"%'"+
|
|
||||||
" ORDER BY id "+sort,
|
|
||||||
null);
|
|
||||||
ArrayList<ResultItem> list = new ArrayList<>();
|
|
||||||
//
|
|
||||||
// if(cursor.moveToFirst()){
|
|
||||||
// do {
|
|
||||||
// // on below line we are adding the data from cursor to our array list.
|
|
||||||
// list.add(new ResultItem(cursor.getInt(cursor.getColumnIndex(id)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(url)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(title)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(author)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(duration)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(thumb)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(type)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(time)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(downloadPath)),
|
|
||||||
// cursor.getString(cursor.getColumnIndex(website)),
|
|
||||||
// cursor.getInt(cursor.getColumnIndex(isQueuedDownload))));
|
|
||||||
// } while (cursor.moveToNext());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cursor.close();
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addToResults(ArrayList<ResultItem> videot){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
|
|
||||||
// for(ResultItem v : videot){
|
|
||||||
// values.put(videoId, v.getVideoId());
|
|
||||||
// values.put(url, v.getURL());
|
|
||||||
// values.put(title, v.getTitle());
|
|
||||||
// values.put(author, v.getAuthor());
|
|
||||||
// values.put(duration, v.getDuration());
|
|
||||||
// values.put(thumb, v.getThumb());
|
|
||||||
// values.put(downloadedAudio, v.isAudioDownloaded());
|
|
||||||
// values.put(downloadedVideo, v.isVideoDownloaded());
|
|
||||||
// values.put(isPlaylistItem, v.getIsPlaylistItem());
|
|
||||||
// values.put(website, v.getWebsite());
|
|
||||||
// values.put(downloadingAudio, 0);
|
|
||||||
// values.put(downloadingVideo, 0);
|
|
||||||
// values.put(playlistTitle, v.getPlaylistTitle());
|
|
||||||
//
|
|
||||||
// db.insert(results_table_name, null, values);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addToHistory(ResultItem v){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
//
|
|
||||||
// values.put(url, v.getURL());
|
|
||||||
// values.put(title, v.getTitle());
|
|
||||||
// values.put(author, v.getAuthor());
|
|
||||||
// values.put(duration, v.getDuration());
|
|
||||||
// values.put(thumb, v.getThumb());
|
|
||||||
// values.put(type, v.getDownloadedType());
|
|
||||||
// values.put(time, v.getDownloadedTime());
|
|
||||||
// values.put(downloadPath, v.getDownloadPath());
|
|
||||||
// values.put(website, v.getWebsite());
|
|
||||||
// values.put(isQueuedDownload, (v.isQueuedDownload()) ? 1 : 0);
|
|
||||||
//
|
|
||||||
// db.insert(history_table_name, null, values);
|
|
||||||
// db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateHistoryItem(ResultItem v){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
|
|
||||||
// values.put(url, v.getURL());
|
|
||||||
// values.put(title, v.getTitle());
|
|
||||||
// values.put(author, v.getAuthor());
|
|
||||||
// values.put(duration, v.getDuration());
|
|
||||||
// values.put(thumb, v.getThumb());
|
|
||||||
// values.put(type, v.getDownloadedType());
|
|
||||||
// values.put(time, v.getDownloadedTime());
|
|
||||||
// values.put(downloadPath, v.getDownloadPath());
|
|
||||||
// values.put(website, v.getWebsite());
|
|
||||||
// values.put(isQueuedDownload, (v.isQueuedDownload()) ? 1 : 0);
|
|
||||||
//
|
|
||||||
// String where = url + "='"+v.getURL()+"' AND "+isQueuedDownload+"=1 AND "+type+"='"+v.getDownloadedType()+"'";
|
|
||||||
// db.update(history_table_name, values, where, null);
|
|
||||||
// db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateDownloadStatusOnResult(String id, String type, boolean downloaded){
|
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
|
|
||||||
switch (type){
|
|
||||||
case "audio":
|
|
||||||
if (downloaded) values.put(downloadedAudio, 1);
|
|
||||||
values.put(downloadingAudio, 0);
|
|
||||||
break;
|
|
||||||
case "video":
|
|
||||||
if (downloaded) values.put(downloadedVideo, 1);
|
|
||||||
values.put(downloadingVideo, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
db.update(results_table_name, values, "videoId = ?", new String[]{id});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateDownloadingStatusOnResult(String id, String type, boolean downloading){
|
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
type = (type.equals("audio")) ? downloadingAudio : downloadingVideo;
|
|
||||||
int value = (downloading) ? 1 : 0;
|
|
||||||
values.put(type, value);
|
|
||||||
|
|
||||||
db.update(results_table_name, values, "videoId = ?", new String[]{id});
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("Range")
|
|
||||||
public int checkDownloaded(String url, String downloadType){
|
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
|
||||||
Cursor cursor = db.rawQuery("SELECT * FROM " + history_table_name + " WHERE url='" +
|
|
||||||
url + "' AND type='"+downloadType + "' LIMIT 1", null);
|
|
||||||
|
|
||||||
if(cursor.moveToFirst()){
|
|
||||||
String path = cursor.getString(cursor.getColumnIndex(downloadPath));
|
|
||||||
File file = new File(path);
|
|
||||||
if(!file.exists() && !path.isEmpty()){
|
|
||||||
return 0;
|
|
||||||
}else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.service;
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
public class DownloadInfo {
|
|
||||||
private ResultItem video;
|
|
||||||
private int progress;
|
|
||||||
private LinkedList<ResultItem> downloadQueue;
|
|
||||||
private String outputLine;
|
|
||||||
private String downloadStatus;
|
|
||||||
private String downloadPath;
|
|
||||||
private String downloadType;
|
|
||||||
|
|
||||||
public DownloadInfo(){}
|
|
||||||
|
|
||||||
public ResultItem getVideo() {
|
|
||||||
return video;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVideo(ResultItem video) {
|
|
||||||
this.video = video;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getProgress() {
|
|
||||||
return progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProgress(int progress) {
|
|
||||||
this.progress = progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LinkedList<ResultItem> getDownloadQueue() {
|
|
||||||
return downloadQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloadQueue(LinkedList<ResultItem> downloadQueue) {
|
|
||||||
this.downloadQueue = downloadQueue;
|
|
||||||
this.video = downloadQueue.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOutputLine() {
|
|
||||||
return outputLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutputLine(String outputLine) {
|
|
||||||
this.outputLine = outputLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDownloadStatus(){
|
|
||||||
return downloadStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloadStatus(String status){
|
|
||||||
downloadStatus = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDownloadPath(){
|
|
||||||
return downloadPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloadPath(String path){
|
|
||||||
this.downloadPath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDownloadType() {
|
|
||||||
return downloadType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloadType(String downloadType) {
|
|
||||||
this.downloadType = downloadType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.deniscerri.ytdlnis.service
|
||||||
|
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class DownloadInfo {
|
||||||
|
var video: ResultItem? = null
|
||||||
|
var progress = 0
|
||||||
|
var downloadQueue: LinkedList<ResultItem>? = null
|
||||||
|
private set
|
||||||
|
var outputLine: String? = null
|
||||||
|
var downloadStatus: String? = null
|
||||||
|
var downloadPath: String? = null
|
||||||
|
var downloadType: String? = null
|
||||||
|
fun setDownloadQueue(downloadQueue: LinkedList<ResultItem>) {
|
||||||
|
this.downloadQueue = downloadQueue
|
||||||
|
video = downloadQueue.peek()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.service;
|
|
||||||
|
|
||||||
public interface IDownloaderListener {
|
|
||||||
void onDownloadStart(DownloadInfo downloadInfo);
|
|
||||||
void onDownloadProgress(DownloadInfo downloadInfo);
|
|
||||||
void onDownloadError(DownloadInfo downloadInfo);
|
|
||||||
void onDownloadEnd(DownloadInfo downloadInfo);
|
|
||||||
void onDownloadCancel(DownloadInfo downloadInfo);
|
|
||||||
void onDownloadCancelAll(DownloadInfo downloadInfo);
|
|
||||||
void onDownloadServiceEnd();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.deniscerri.ytdlnis.service
|
||||||
|
|
||||||
|
interface IDownloaderListener {
|
||||||
|
fun onDownloadStart(downloadInfo: DownloadInfo?)
|
||||||
|
fun onDownloadProgress(downloadInfo: DownloadInfo?)
|
||||||
|
fun onDownloadError(downloadInfo: DownloadInfo?)
|
||||||
|
fun onDownloadEnd(downloadInfo: DownloadInfo?)
|
||||||
|
fun onDownloadCancel(downloadInfo: DownloadInfo?)
|
||||||
|
fun onDownloadCancelAll(downloadInfo: DownloadInfo?)
|
||||||
|
fun onDownloadServiceEnd()
|
||||||
|
}
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.service;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public interface IDownloaderService {
|
|
||||||
DownloadInfo getInfo();
|
|
||||||
void addActivity(Activity activity, ArrayList<IDownloaderListener> callback);
|
|
||||||
void removeActivity(Activity activity);
|
|
||||||
void updateQueue(ArrayList<ResultItem> queue);
|
|
||||||
void cancelDownload(boolean cancelAll);
|
|
||||||
void removeItemFromDownloadQueue(ResultItem video, String type);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.deniscerri.ytdlnis.service
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
|
||||||
|
interface IDownloaderService {
|
||||||
|
val info: DownloadInfo?
|
||||||
|
fun addActivity(activity: Activity?, callback: ArrayList<IDownloaderListener?>?)
|
||||||
|
fun removeActivity(activity: Activity?)
|
||||||
|
fun updateQueue(queue: ArrayList<ResultItem?>?)
|
||||||
|
fun cancelDownload(cancelAll: Boolean)
|
||||||
|
fun removeItemFromDownloadQueue(video: ResultItem?, type: String?)
|
||||||
|
}
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.service.api
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Response
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
|
||||||
import retrofit2.http.GET
|
|
||||||
import retrofit2.http.Path
|
|
||||||
|
|
||||||
interface InvidiousService {
|
|
||||||
@GET("video/{id}")
|
|
||||||
suspend fun getVideo(
|
|
||||||
@Path("id") id : String
|
|
||||||
) : Call<ResultItem>
|
|
||||||
|
|
||||||
@GET("playlist/{id}")
|
|
||||||
suspend fun getPlaylist(
|
|
||||||
@Path("id") id: String
|
|
||||||
) : Response<JsonObject>
|
|
||||||
|
|
||||||
@GET("trending?type=music®ion={regionCode}")
|
|
||||||
suspend fun getTrending(
|
|
||||||
@Path("regionCode") regionCode: String
|
|
||||||
) : Response<JsonArray>
|
|
||||||
|
|
||||||
@GET("search/suggestions?q={query}")
|
|
||||||
suspend fun getSearchSuggestions(
|
|
||||||
@Path("query") query: String
|
|
||||||
) : Response<JsonObject>
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
var invidiousService : InvidiousService? = null
|
|
||||||
fun getInstance() : InvidiousService {
|
|
||||||
return invidiousService ?: run {
|
|
||||||
val retrofit = Retrofit.Builder()
|
|
||||||
.baseUrl("https://invidious.baczek.me/api/v1/")
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.build()
|
|
||||||
invidiousService = retrofit.create(InvidiousService::class.java)
|
|
||||||
invidiousService!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.service.api
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import retrofit2.Response
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
|
||||||
import retrofit2.http.GET
|
|
||||||
import retrofit2.http.Path
|
|
||||||
|
|
||||||
interface YoutubeAPIService {
|
|
||||||
@GET("videos?part=snippet,contentDetails&id={id}&key={apiKey}")
|
|
||||||
suspend fun getVideo(
|
|
||||||
@Path("id") id: String?
|
|
||||||
) : Response<JsonObject>
|
|
||||||
|
|
||||||
@GET("playlistItems?part=snippet&pageToken={nextPageToken}&maxResults=50®ionCode={regionCode}&playlistId={playlistId}&key={apiKey}")
|
|
||||||
suspend fun getPlaylist(
|
|
||||||
@Path("nextPageToken") nextPageToken: String,
|
|
||||||
@Path("playlistId") playlistId : String,
|
|
||||||
@Path("apiKey") apiKey : String
|
|
||||||
) : Response<JsonObject>
|
|
||||||
|
|
||||||
@GET("videos?part=snippet&chart=mostPopular&videoCategoryId=10®ionCode={regionCode}&maxResults=25&key={apiKey}")
|
|
||||||
suspend fun getTrending(
|
|
||||||
@Path("regionCode") regionCode: String,
|
|
||||||
@Path("apiKey") apiKey : String
|
|
||||||
) : Response<JsonArray>
|
|
||||||
|
|
||||||
@GET("videos?part=contentDetails&chart=mostPopular&videoCategoryId=10®ionCode={regionCode}&maxResults=25&key={apiKey}")
|
|
||||||
suspend fun getTrendingExtra(
|
|
||||||
@Path("regionCode") regionCode: String,
|
|
||||||
@Path("apiKey") apiKey : String
|
|
||||||
) : Response<JsonArray>
|
|
||||||
|
|
||||||
@GET("search?part=snippet&q={query}&maxResults=25®ionCode={regionCode}&key={apiKey}")
|
|
||||||
suspend fun search(
|
|
||||||
@Path("query") query: String,
|
|
||||||
@Path("regionCode") regionCode: String,
|
|
||||||
@Path("apiKey") apiKey: String
|
|
||||||
) : Response<JsonObject>
|
|
||||||
|
|
||||||
@GET("videos?id={ids}&part=contentDetails®ionCode={regionCode}&key={apiKey}")
|
|
||||||
suspend fun getExtraData(
|
|
||||||
@Path("ids") ids: String,
|
|
||||||
@Path("regionCode") regionCode: String,
|
|
||||||
@Path("apiKey") apiKey: String
|
|
||||||
) : Response<JsonObject>
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
var invidiousService : YoutubeAPIService? = null
|
|
||||||
lateinit var apiKey : String
|
|
||||||
lateinit var regionCode: String
|
|
||||||
fun getInstance(key: String, regionCode: String) : YoutubeAPIService {
|
|
||||||
apiKey = key
|
|
||||||
return invidiousService ?: run {
|
|
||||||
val retrofit = Retrofit.Builder()
|
|
||||||
.baseUrl("https://www.googleapis.com/youtube/v3/")
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.build()
|
|
||||||
invidiousService = retrofit.create(YoutubeAPIService::class.java)
|
|
||||||
invidiousService!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,213 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.ui;
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.media.MediaScannerConnection;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.text.method.ScrollingMovementMethod;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ScrollView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import com.deniscerri.ytdlnis.R;
|
|
||||||
import com.deniscerri.ytdlnis.DownloaderService;
|
|
||||||
import com.deniscerri.ytdlnis.service.DownloadInfo;
|
|
||||||
import com.deniscerri.ytdlnis.service.IDownloaderListener;
|
|
||||||
import com.deniscerri.ytdlnis.service.IDownloaderService;
|
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil;
|
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class CustomCommandActivity extends AppCompatActivity {
|
|
||||||
private static final String TAG = "CustomCommandActivity";
|
|
||||||
private MaterialToolbar topAppBar;
|
|
||||||
private boolean isDownloadServiceRunning = false;
|
|
||||||
public DownloaderService downloaderService;
|
|
||||||
private TextView output;
|
|
||||||
private EditText input;
|
|
||||||
private ExtendedFloatingActionButton fab;
|
|
||||||
private ExtendedFloatingActionButton cancelFab;
|
|
||||||
private IDownloaderService iDownloaderService;
|
|
||||||
private ScrollView scrollView;
|
|
||||||
Context context;
|
|
||||||
|
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
|
||||||
@Override
|
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
|
||||||
downloaderService = ((DownloaderService.LocalBinder) service).getService();
|
|
||||||
iDownloaderService = (IDownloaderService) service;
|
|
||||||
isDownloadServiceRunning = true;
|
|
||||||
try{
|
|
||||||
ArrayList<IDownloaderListener> listeners = new ArrayList<>();
|
|
||||||
listeners.add(listener);
|
|
||||||
iDownloaderService.addActivity(CustomCommandActivity.this, listeners);
|
|
||||||
listener.onDownloadStart(iDownloaderService.getInfo());
|
|
||||||
}catch(Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceDisconnected(ComponentName componentName) {
|
|
||||||
downloaderService = null;
|
|
||||||
iDownloaderService = null;
|
|
||||||
isDownloadServiceRunning = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public IDownloaderListener listener = new IDownloaderListener() {
|
|
||||||
|
|
||||||
public void onDownloadStart(DownloadInfo info) {
|
|
||||||
input.setEnabled(false);
|
|
||||||
output.setText("");
|
|
||||||
swapFabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDownloadProgress(DownloadInfo info) {
|
|
||||||
String newInfo = info.getOutputLine();
|
|
||||||
if (newInfo.contains("[download]")){
|
|
||||||
String temp = output.getText().toString();
|
|
||||||
output.setText(
|
|
||||||
temp.substring(0, temp.lastIndexOf(System.getProperty("line.separator")) - 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
output.append(info.getOutputLine() + " \n");
|
|
||||||
output.scrollTo(0, output.getHeight());
|
|
||||||
scrollView.fullScroll(View.FOCUS_DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDownloadError(DownloadInfo info) {
|
|
||||||
output.append("\n" + info.getOutputLine());
|
|
||||||
scrollView.scrollTo(0, scrollView.getMaxScrollAmount());
|
|
||||||
input.setText("yt-dlp ");
|
|
||||||
input.setEnabled(true);
|
|
||||||
swapFabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDownloadEnd(DownloadInfo info) {
|
|
||||||
output.append(info.getOutputLine());
|
|
||||||
scrollView.scrollTo(0, scrollView.getMaxScrollAmount());
|
|
||||||
// MEDIA SCAN
|
|
||||||
MediaScannerConnection.scanFile(context, new String[]{"/storage"}, null, null);
|
|
||||||
input.setText("yt-dlp ");
|
|
||||||
input.setEnabled(true);
|
|
||||||
swapFabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDownloadCancel(DownloadInfo downloadInfo) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDownloadCancelAll(DownloadInfo downloadInfo){}
|
|
||||||
|
|
||||||
public void onDownloadServiceEnd() {
|
|
||||||
stopDownloadService();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_custom_command);
|
|
||||||
|
|
||||||
context = getBaseContext();
|
|
||||||
scrollView = findViewById(R.id.custom_command_scrollview);
|
|
||||||
topAppBar = findViewById(R.id.custom_command_toolbar);
|
|
||||||
topAppBar.setNavigationOnClickListener(view -> onBackPressed());
|
|
||||||
output = findViewById(R.id.custom_command_output);
|
|
||||||
output.setTextIsSelectable(true);
|
|
||||||
|
|
||||||
input = findViewById(R.id.command_edittext);
|
|
||||||
input.requestFocus();
|
|
||||||
|
|
||||||
fab = findViewById(R.id.command_fab);
|
|
||||||
fab.setOnClickListener(view -> {
|
|
||||||
if (isStoragePermissionGranted()){
|
|
||||||
startDownloadService(input.getText().toString(), NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
cancelFab = findViewById(R.id.cancel_command_fab);
|
|
||||||
cancelFab.setOnClickListener(view -> {
|
|
||||||
cancelDownloadService();
|
|
||||||
swapFabs();
|
|
||||||
input.setEnabled(true);
|
|
||||||
});
|
|
||||||
handleIntent(getIntent());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onNewIntent(Intent intent) {
|
|
||||||
super.onNewIntent(intent);
|
|
||||||
handleIntent(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleIntent(Intent intent){
|
|
||||||
String action = intent.getAction();
|
|
||||||
String type = intent.getType();
|
|
||||||
Log.e(TAG, action + " " + type);
|
|
||||||
if (action.equals(Intent.ACTION_SEND) && type != null) {
|
|
||||||
Log.e(TAG, action);
|
|
||||||
String txt = "yt-dlp " + intent.getStringExtra(Intent.EXTRA_TEXT);
|
|
||||||
input.setText(txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void swapFabs(){
|
|
||||||
int cancel = cancelFab.getVisibility();
|
|
||||||
int start = fab.getVisibility();
|
|
||||||
cancelFab.setVisibility(start);
|
|
||||||
fab.setVisibility(cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
super.onBackPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void startDownloadService(String command, int id){
|
|
||||||
if(isDownloadServiceRunning) return;
|
|
||||||
Intent serviceIntent = new Intent(context, DownloaderService.class);
|
|
||||||
serviceIntent.putExtra("command", command);
|
|
||||||
serviceIntent.putExtra("id", id);
|
|
||||||
context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopDownloadService(){
|
|
||||||
if(!isDownloadServiceRunning) return;
|
|
||||||
iDownloaderService.removeActivity(this);
|
|
||||||
context.getApplicationContext().unbindService(serviceConnection);
|
|
||||||
downloaderService.stopForeground(true);
|
|
||||||
downloaderService.stopSelf();
|
|
||||||
isDownloadServiceRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancelDownloadService(){
|
|
||||||
if(!isDownloadServiceRunning) return;
|
|
||||||
iDownloaderService.cancelDownload(false);
|
|
||||||
stopDownloadService();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isStoragePermissionGranted() {
|
|
||||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
package com.deniscerri.ytdlnis.ui
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.media.MediaScannerConnection
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.ScrollView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import com.deniscerri.ytdlnis.DownloaderService
|
||||||
|
import com.deniscerri.ytdlnis.DownloaderService.LocalBinder
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.service.DownloadInfo
|
||||||
|
import com.deniscerri.ytdlnis.service.IDownloaderListener
|
||||||
|
import com.deniscerri.ytdlnis.service.IDownloaderService
|
||||||
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
|
||||||
|
class CustomCommandActivity : AppCompatActivity() {
|
||||||
|
private var topAppBar: MaterialToolbar? = null
|
||||||
|
private var isDownloadServiceRunning = false
|
||||||
|
var downloaderService: DownloaderService? = null
|
||||||
|
private var output: TextView? = null
|
||||||
|
private var input: EditText? = null
|
||||||
|
private var fab: ExtendedFloatingActionButton? = null
|
||||||
|
private var cancelFab: ExtendedFloatingActionButton? = null
|
||||||
|
private var iDownloaderService: IDownloaderService? = null
|
||||||
|
private var scrollView: ScrollView? = null
|
||||||
|
var context: Context? = null
|
||||||
|
private val serviceConnection: ServiceConnection = object : ServiceConnection {
|
||||||
|
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||||
|
downloaderService = (service as LocalBinder).service
|
||||||
|
iDownloaderService = service
|
||||||
|
isDownloadServiceRunning = true
|
||||||
|
try {
|
||||||
|
val listeners = ArrayList<IDownloaderListener>()
|
||||||
|
listeners.add(listener)
|
||||||
|
iDownloaderService!!.addActivity(this@CustomCommandActivity, listeners)
|
||||||
|
listener.onDownloadStart(iDownloaderService!!.info)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(componentName: ComponentName) {
|
||||||
|
downloaderService = null
|
||||||
|
iDownloaderService = null
|
||||||
|
isDownloadServiceRunning = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var listener: IDownloaderListener = object : IDownloaderListener {
|
||||||
|
override fun onDownloadStart(info: DownloadInfo) {
|
||||||
|
input!!.isEnabled = false
|
||||||
|
output!!.text = ""
|
||||||
|
swapFabs()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDownloadProgress(info: DownloadInfo) {
|
||||||
|
val newInfo = info.outputLine
|
||||||
|
if (newInfo.contains("[download]")) {
|
||||||
|
val temp = output!!.text.toString()
|
||||||
|
output!!.text =
|
||||||
|
temp.substring(0, temp.lastIndexOf(System.getProperty("line.separator")!!) - 2)
|
||||||
|
}
|
||||||
|
output!!.append(
|
||||||
|
"""${info.outputLine}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output!!.scrollTo(0, output!!.height)
|
||||||
|
scrollView!!.fullScroll(View.FOCUS_DOWN)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun onDownloadError(info: DownloadInfo) {
|
||||||
|
output!!.append(
|
||||||
|
"""
|
||||||
|
|
||||||
|
${info.outputLine}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
scrollView!!.scrollTo(0, scrollView!!.maxScrollAmount)
|
||||||
|
input!!.setText("yt-dlp ")
|
||||||
|
input!!.isEnabled = true
|
||||||
|
swapFabs()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun onDownloadEnd(info: DownloadInfo) {
|
||||||
|
output!!.append(info.outputLine)
|
||||||
|
scrollView!!.scrollTo(0, scrollView!!.maxScrollAmount)
|
||||||
|
// MEDIA SCAN
|
||||||
|
MediaScannerConnection.scanFile(context, arrayOf("/storage"), null, null)
|
||||||
|
input!!.setText("yt-dlp ")
|
||||||
|
input!!.isEnabled = true
|
||||||
|
swapFabs()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDownloadCancel(downloadInfo: DownloadInfo) {}
|
||||||
|
override fun onDownloadCancelAll(downloadInfo: DownloadInfo) {}
|
||||||
|
override fun onDownloadServiceEnd() {
|
||||||
|
stopDownloadService()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_custom_command)
|
||||||
|
context = baseContext
|
||||||
|
scrollView = findViewById(R.id.custom_command_scrollview)
|
||||||
|
topAppBar = findViewById(R.id.custom_command_toolbar)
|
||||||
|
topAppBar!!.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
||||||
|
output = findViewById(R.id.custom_command_output)
|
||||||
|
output!!.setTextIsSelectable(true)
|
||||||
|
input = findViewById(R.id.command_edittext)
|
||||||
|
input!!.requestFocus()
|
||||||
|
fab = findViewById(R.id.command_fab)
|
||||||
|
fab!!.setOnClickListener {
|
||||||
|
if (isStoragePermissionGranted) {
|
||||||
|
startDownloadService(
|
||||||
|
input!!.text.toString(),
|
||||||
|
NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cancelFab = findViewById(R.id.cancel_command_fab)
|
||||||
|
cancelFab!!.setOnClickListener {
|
||||||
|
cancelDownloadService()
|
||||||
|
swapFabs()
|
||||||
|
input!!.isEnabled = true
|
||||||
|
}
|
||||||
|
handleIntent(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
handleIntent(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent(intent: Intent) {
|
||||||
|
val action = intent.action
|
||||||
|
val type = intent.type
|
||||||
|
Log.e(TAG, "$action $type")
|
||||||
|
if (action == Intent.ACTION_SEND && type != null) {
|
||||||
|
Log.e(TAG, action)
|
||||||
|
val txt = "yt-dlp " + intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||||
|
input!!.setText(txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun swapFabs() {
|
||||||
|
val cancel = cancelFab!!.visibility
|
||||||
|
val start = fab!!.visibility
|
||||||
|
cancelFab!!.visibility = start
|
||||||
|
fab!!.visibility = cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun startDownloadService(command: String?, id: Int) {
|
||||||
|
if (isDownloadServiceRunning) return
|
||||||
|
val serviceIntent = Intent(context, DownloaderService::class.java)
|
||||||
|
serviceIntent.putExtra("command", command)
|
||||||
|
serviceIntent.putExtra("id", id)
|
||||||
|
context!!.applicationContext.bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopDownloadService() {
|
||||||
|
if (!isDownloadServiceRunning) return
|
||||||
|
iDownloaderService!!.removeActivity(this)
|
||||||
|
context!!.applicationContext.unbindService(serviceConnection)
|
||||||
|
downloaderService!!.stopForeground(true)
|
||||||
|
downloaderService!!.stopSelf()
|
||||||
|
isDownloadServiceRunning = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelDownloadService() {
|
||||||
|
if (!isDownloadServiceRunning) return
|
||||||
|
iDownloaderService!!.cancelDownload(false)
|
||||||
|
stopDownloadService()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val isStoragePermissionGranted: Boolean
|
||||||
|
get() = if (ActivityCompat.checkSelfPermission(
|
||||||
|
this,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
|
== PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
this,
|
||||||
|
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
|
||||||
|
1
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "CustomCommandActivity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.adapter.HistoryAdapter
|
import com.deniscerri.ytdlnis.adapter.HistoryAdapter
|
||||||
import com.deniscerri.ytdlnis.database.DatabaseManager
|
|
||||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.HistoryRepository.HistorySort
|
import com.deniscerri.ytdlnis.database.repository.HistoryRepository.HistorySort
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel
|
||||||
|
|
@ -45,7 +44,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
|
|
||||||
private var downloading = false
|
private var downloading = false
|
||||||
private var fragmentView: View? = null
|
private var fragmentView: View? = null
|
||||||
private var databaseManager: DatabaseManager? = null
|
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private var mainActivity: MainActivity? = null
|
private var mainActivity: MainActivity? = null
|
||||||
private var fragmentContext: Context? = null
|
private var fragmentContext: Context? = null
|
||||||
|
|
@ -165,7 +163,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
val searchView = topAppBar!!.menu.findItem(R.id.search_downloads).actionView as SearchView?
|
val searchView = topAppBar!!.menu.findItem(R.id.search_downloads).actionView as SearchView?
|
||||||
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
||||||
searchView.queryHint = getString(R.string.search_history_hint)
|
searchView.queryHint = getString(R.string.search_history_hint)
|
||||||
databaseManager = DatabaseManager(context)
|
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
topAppBar!!.menu.findItem(R.id.search_downloads).collapseActionView()
|
topAppBar!!.menu.findItem(R.id.search_downloads).collapseActionView()
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
|
@ -23,7 +22,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
||||||
import com.deniscerri.ytdlnis.database.DatabaseManager
|
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
|
|
@ -37,18 +35,13 @@ import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
import com.facebook.shimmer.ShimmerFrameLayout
|
import com.facebook.shimmer.ShimmerFrameLayout
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.chip.ChipGroup
|
import com.google.android.material.chip.ChipGroup
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
|
||||||
import java.text.DecimalFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.log10
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
||||||
private var progressBar: LinearProgressIndicator? = null
|
private var progressBar: LinearProgressIndicator? = null
|
||||||
|
|
@ -70,7 +63,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
|
|
||||||
private var downloading = false
|
private var downloading = false
|
||||||
private var fragmentView: View? = null
|
private var fragmentView: View? = null
|
||||||
private var databaseManager: DatabaseManager? = null
|
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private var mainActivity: MainActivity? = null
|
private var mainActivity: MainActivity? = null
|
||||||
private var fragmentContext: Context? = null
|
private var fragmentContext: Context? = null
|
||||||
|
|
@ -239,7 +231,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
val searchView = topAppBar!!.menu.findItem(R.id.search).actionView as SearchView?
|
val searchView = topAppBar!!.menu.findItem(R.id.search).actionView as SearchView?
|
||||||
searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_URI
|
searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_URI
|
||||||
searchView.queryHint = getString(R.string.search_hint)
|
searchView.queryHint = getString(R.string.search_hint)
|
||||||
databaseManager = DatabaseManager(context)
|
|
||||||
infoUtil = InfoUtil(requireContext())
|
infoUtil = InfoUtil(requireContext())
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
|
|
@ -390,7 +381,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) {
|
downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) {
|
||||||
downloadItem.id = it
|
downloadItem.id = it
|
||||||
val bottomSheet = DownloadBottomSheetDialog(downloadItem)
|
val bottomSheet = DownloadBottomSheetDialog(downloadItem)
|
||||||
bottomSheet.show(parentFragmentManager, "bottomSheet")
|
bottomSheet.show(parentFragmentManager, "downloadSingleSheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.ui;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
|
||||||
import com.deniscerri.ytdlnis.R;
|
|
||||||
|
|
||||||
public class MoreFragment extends PreferenceFragmentCompat {
|
|
||||||
public static final String TAG = "MoreFragment";
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
setPreferencesFromResource(R.xml.more_preferences, rootKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
app/src/main/java/com/deniscerri/ytdlnis/ui/MoreFragment.kt
Normal file
15
app/src/main/java/com/deniscerri/ytdlnis/ui/MoreFragment.kt
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.deniscerri.ytdlnis.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
|
||||||
|
class MoreFragment : PreferenceFragmentCompat() {
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.more_preferences, rootKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "MoreFragment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import androidx.fragment.app.FragmentTransaction
|
import androidx.fragment.app.FragmentTransaction
|
||||||
import androidx.fragment.app.findFragment
|
import androidx.fragment.app.findFragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
|
@ -13,6 +14,8 @@ import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
|
||||||
|
|
@ -28,11 +31,18 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val behavior = BottomSheetBehavior.from(view.parent as View)
|
||||||
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
override fun setupDialog(dialog: Dialog, style: Int) {
|
override fun setupDialog(dialog: Dialog, style: Int) {
|
||||||
super.setupDialog(dialog, style)
|
super.setupDialog(dialog, style)
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.download_bottom_sheet, null)
|
val view = LayoutInflater.from(context).inflate(R.layout.download_bottom_sheet, null)
|
||||||
dialog.setContentView(view)
|
dialog.setContentView(view)
|
||||||
|
//view.minimumHeight = resources.displayMetrics.heightPixels
|
||||||
|
|
||||||
tabLayout = view.findViewById(R.id.download_tablayout)
|
tabLayout = view.findViewById(R.id.download_tablayout)
|
||||||
viewPager2 = view.findViewById(R.id.download_viewpager)
|
viewPager2 = view.findViewById(R.id.download_viewpager)
|
||||||
|
|
@ -79,7 +89,7 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
|
||||||
|
|
||||||
override fun onCancel(dialog: DialogInterface) {
|
override fun onCancel(dialog: DialogInterface) {
|
||||||
super.onCancel(dialog)
|
super.onCancel(dialog)
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("bottomSheet")!!).commit()
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadSingleSheet")!!).commit()
|
||||||
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
||||||
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.ui.settings;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.R;
|
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
|
||||||
|
|
||||||
|
|
||||||
public class SettingsActivity extends AppCompatActivity{
|
|
||||||
|
|
||||||
private FragmentManager fm;
|
|
||||||
private MaterialToolbar topAppBar;
|
|
||||||
Context context;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_settings);
|
|
||||||
context = getBaseContext();
|
|
||||||
topAppBar = findViewById(R.id.settings_toolbar);
|
|
||||||
topAppBar.setNavigationOnClickListener(view -> onBackPressed());
|
|
||||||
fm = getSupportFragmentManager();
|
|
||||||
fm.beginTransaction()
|
|
||||||
.replace(R.id.settings_frame_layout, new SettingsFragment())
|
|
||||||
.commit();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
super.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.deniscerri.ytdlnis.ui.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
|
||||||
|
class SettingsActivity : AppCompatActivity() {
|
||||||
|
private var fm: FragmentManager? = null
|
||||||
|
private var topAppBar: MaterialToolbar? = null
|
||||||
|
var context: Context? = null
|
||||||
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_settings)
|
||||||
|
context = baseContext
|
||||||
|
topAppBar = findViewById(R.id.settings_toolbar)
|
||||||
|
topAppBar!!.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
||||||
|
fm = supportFragmentManager
|
||||||
|
fm!!.beginTransaction()
|
||||||
|
.replace(R.id.settings_frame_layout, SettingsFragment())
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,6 @@ import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.DatabaseManager
|
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItemWithFormats
|
import com.deniscerri.ytdlnis.database.models.ResultItemWithFormats
|
||||||
|
|
@ -26,14 +25,12 @@ class InfoUtil(context: Context) {
|
||||||
private var items: ArrayList<ResultItemWithFormats?>
|
private var items: ArrayList<ResultItemWithFormats?>
|
||||||
private var key: String? = null
|
private var key: String? = null
|
||||||
private var useInvidous = false
|
private var useInvidous = false
|
||||||
private var databaseManager: DatabaseManager? = null
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
try {
|
||||||
val sharedPreferences =
|
val sharedPreferences =
|
||||||
context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
key = sharedPreferences.getString("api_key", "")
|
key = sharedPreferences.getString("api_key", "")
|
||||||
databaseManager = DatabaseManager(context)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
@ -258,9 +255,6 @@ class InfoUtil(context: Context) {
|
||||||
val duration = obj.getString("duration")
|
val duration = obj.getString("duration")
|
||||||
val thumb = obj.getString("thumb")
|
val thumb = obj.getString("thumb")
|
||||||
val url = "https://www.youtube.com/watch?v=$id"
|
val url = "https://www.youtube.com/watch?v=$id"
|
||||||
val downloadedAudio = databaseManager!!.checkDownloaded(url, "audio")
|
|
||||||
val downloadedVideo = databaseManager!!.checkDownloaded(url, "video")
|
|
||||||
val isPlaylist = 0
|
|
||||||
video = ResultItemWithFormats(
|
video = ResultItemWithFormats(
|
||||||
ResultItem(0,
|
ResultItem(0,
|
||||||
url,
|
url,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<vector android:height="24dp" android:tint="#00A6FF"
|
<vector android:height="24dp"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M14,2H6C4.9,2 4,2.9 4,4v16c0,1.1 0.89,2 1.99,2H15v-8h5V8L14,2zM13,9V3.5L18.5,9H13zM17,21.66V16h5.66v2h-2.24l2.95,2.95l-1.41,1.41L19,19.41l0,2.24H17z"/>
|
<path android:fillColor="?android:colorAccent" android:pathData="M14,2H6C4.9,2 4,2.9 4,4v16c0,1.1 0.89,2 1.99,2H15v-8h5V8L14,2zM13,9V3.5L18.5,9H13zM17,21.66V16h5.66v2h-2.24l2.95,2.95l-1.41,1.41L19,19.41l0,2.24H17z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/ic_download_type.xml
Normal file
5
app/src/main/res/drawable/ic_download_type.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="?android:textColorPrimary" android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,19L3,19L3,5h18v14zM8,15c0,-1.66 1.34,-3 3,-3 0.35,0 0.69,0.07 1,0.18L12,6h5v2h-3v7.03c-0.02,1.64 -1.35,2.97 -3,2.97 -1.66,0 -3,-1.34 -3,-3z"/>
|
||||||
|
</vector>
|
||||||
5
app/src/main/res/drawable/ic_format.xml
Normal file
5
app/src/main/res/drawable/ic_format.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="?android:textColorPrimary" android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM11,15L9.5,15v-2h-2v2L6,15L6,9h1.5v2.5h2L9.5,9L11,9v6zM13,9h4c0.55,0 1,0.45 1,1v4c0,0.55 -0.45,1 -1,1h-4L13,9zM14.5,13.5h2v-3h-2v3z"/>
|
||||||
|
</vector>
|
||||||
5
app/src/main/res/drawable/ic_handle.xml
Normal file
5
app/src/main/res/drawable/ic_handle.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4V15z"/>
|
||||||
|
</vector>
|
||||||
138
app/src/main/res/layout/download_card.xml
Normal file
138
app/src/main/res/layout/download_card.xml
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/downloads_card_constraintLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/materialButton"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="end"
|
||||||
|
android:padding="0dp"
|
||||||
|
app:icon="@drawable/ic_handle" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/download_card_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="95dp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:checkable="true"
|
||||||
|
app:cardCornerRadius="10dp"
|
||||||
|
app:cardElevation="10dp"
|
||||||
|
app:cardMaxElevation="12dp"
|
||||||
|
app:cardPreventCornerOverlap="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/materialButton"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/downloads_image_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
android:id="@+id/download_progress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:alpha="0.7"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:scaleY="100"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="296dp"
|
||||||
|
android:layout_height="41dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:shadowColor="@color/black"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="17sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/downloads_download_button_type"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/author"
|
||||||
|
android:layout_width="296dp"
|
||||||
|
android:layout_height="23dp"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:shadowColor="@color/black"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowRadius="1.5"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/downloads_download_button_type"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="5dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/author"
|
||||||
|
app:layout_constraintVertical_bias="1.0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/encoding"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="5dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/container" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/filesize"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="5dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/encoding" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/downloads_download_button_type"
|
||||||
|
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||||
|
android:layout_width="55dp"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:cornerRadius="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
101
app/src/main/res/layout/download_multiple_bottom_sheet.xml
Normal file
101
app/src/main/res/layout/download_multiple_bottom_sheet.xml
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bottom_sheet_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/configure_download"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/materialButton"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:gravity="end"
|
||||||
|
app:icon="@drawable/ic_format"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/materialButton2"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/materialButton2"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:gravity="end"
|
||||||
|
app:icon="@drawable/ic_download_type"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/download_multiple_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:id="@+id/bottomsheet_schedule_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:icon="@drawable/ic_clock" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
|
||||||
|
android:id="@+id/bottomsheet_cancel_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:icon="@drawable/ic_cancel" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:id="@+id/bottomsheet_download_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/download"
|
||||||
|
app:icon="@drawable/ic_down"
|
||||||
|
android:autoLink="all"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -166,4 +166,5 @@
|
||||||
<string name="container">Container</string>
|
<string name="container">Container</string>
|
||||||
<string name="template">Template</string>
|
<string name="template">Template</string>
|
||||||
<string name="history">History</string>
|
<string name="history">History</string>
|
||||||
|
<string name="logs">Logs</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:enabled="false"
|
app:enabled="false"
|
||||||
android:layout="@layout/fragment_more"/>
|
android:layout="@layout/fragment_more"/>
|
||||||
|
|
@ -9,6 +10,7 @@
|
||||||
app:icon="@drawable/ic_code"
|
app:icon="@drawable/ic_code"
|
||||||
app:key="rreth"
|
app:key="rreth"
|
||||||
app:summary="https://github.com/deniscerri/ytdlnis"
|
app:summary="https://github.com/deniscerri/ytdlnis"
|
||||||
|
app:allowDividerBelow="true"
|
||||||
app:title="@string/source_code">
|
app:title="@string/source_code">
|
||||||
<intent
|
<intent
|
||||||
android:action="android.intent.action.VIEW"
|
android:action="android.intent.action.VIEW"
|
||||||
|
|
@ -17,13 +19,19 @@
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
|
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
|
||||||
app:allowDividerAbove="true"
|
|
||||||
app:allowDividerBelow="true"
|
|
||||||
app:key="run_command"
|
app:key="run_command"
|
||||||
app:title="@string/custom_command">
|
app:title="@string/custom_command">
|
||||||
<intent android:action="ytdlnis.page.CustomCommandActivity" />
|
<intent android:action="ytdlnis.page.CustomCommandActivity" />
|
||||||
</Preference>
|
</Preference>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:icon="@drawable/ic_baseline_file_open_24"
|
||||||
|
app:key="download_logs"
|
||||||
|
app:allowDividerBelow="true"
|
||||||
|
app:title="@string/logs">
|
||||||
|
<intent android:action="ytdlnis.page.DownloadLogsActivity" />
|
||||||
|
</Preference>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_settings"
|
app:icon="@drawable/ic_settings"
|
||||||
app:key="open_settings"
|
app:key="open_settings"
|
||||||
|
|
@ -32,4 +40,5 @@
|
||||||
</Preference>
|
</Preference>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
Loading…
Reference in a new issue