This commit is contained in:
zaednasr 2024-03-31 22:26:04 +02:00
parent 89e6700db0
commit d7819aca98
No known key found for this signature in database
GPG key ID: 92B1DE23AD3D0E9E
180 changed files with 3001 additions and 1801 deletions

View file

@ -12,14 +12,14 @@ def versionMajor = 1
def versionMinor = 7 def versionMinor = 7
def versionPatch = 4 def versionPatch = 4
def versionBuild = 0 // bump for dogfood builds, public betas, etc. def versionBuild = 0 // bump for dogfood builds, public betas, etc.
def versionExt = ".${versionBuild}" def versionExt = ""
if (versionBuild > 0){ if (versionBuild > 0){
versionExt = ".${versionBuild}-beta" versionExt = ".${versionBuild}-beta"
} }
android { android {
namespace 'com.deniscerri.ytdlnis' namespace 'com.deniscerri.ytdl'
compileSdk 34 compileSdk 34
try { try {

View file

@ -22,10 +22,10 @@
-if @kotlinx.serialization.Serializable class ** -if @kotlinx.serialization.Serializable class **
-keep class androidx.lifecycle.LiveData { *; } -keep class androidx.lifecycle.LiveData { *; }
-keep class com.google.gson.** { *; } -keep class com.google.gson.** { *; }
-keep class com.deniscerri.ytdlnis.database.models.AudioPreferences -keep class com.deniscerri.ytdl.database.models.AudioPreferences
-keep class com.deniscerri.ytdlnis.database.models.VideoPreferences -keep class com.deniscerri.ytdl.database.models.VideoPreferences
-keep class com.deniscerri.ytdlnis.database.models.GithubRelease -keep class com.deniscerri.ytdl.database.models.GithubRelease
-keep class com.deniscerri.ytdlnis.database.models.GithubReleaseAsset -keep class com.deniscerri.ytdl.database.models.GithubReleaseAsset
-keepclassmembers,allowobfuscation class * { -keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>; @com.google.gson.annotations.SerializedName <fields>;
} }

View file

@ -0,0 +1,718 @@
{
"formatVersion": 1,
"database": {
"version": 16,
"identityHash": "6d3700c5756542e79e6368575533f6ed",
"entities": [
{
"tableName": "results",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `website` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `formats` TEXT NOT NULL, `urls` TEXT NOT NULL DEFAULT '', `chapters` TEXT, `playlistURL` TEXT DEFAULT '', `playlistIndex` INTEGER, `creationTime` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "playlistTitle",
"columnName": "playlistTitle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "formats",
"columnName": "formats",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "urls",
"columnName": "urls",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "chapters",
"columnName": "chapters",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "playlistURL",
"columnName": "playlistURL",
"affinity": "TEXT",
"notNull": false,
"defaultValue": "''"
},
{
"fieldPath": "playlistIndex",
"columnName": "playlistIndex",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "creationTime",
"columnName": "creationTime",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "history",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` INTEGER NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `format` TEXT NOT NULL, `downloadId` INTEGER NOT NULL DEFAULT 0, `command` TEXT NOT NULL DEFAULT '')",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downloadPath",
"columnName": "downloadPath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "format",
"columnName": "format",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadId",
"columnName": "downloadId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "command",
"columnName": "command",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "downloads",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `container` TEXT NOT NULL DEFAULT 'Default', `downloadSections` TEXT NOT NULL DEFAULT '', `allFormats` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `audioPreferences` TEXT NOT NULL, `videoPreferences` TEXT NOT NULL, `extraCommands` TEXT NOT NULL DEFAULT '', `customFileNameTemplate` TEXT NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `downloadStartTime` INTEGER NOT NULL DEFAULT 0, `logID` INTEGER, `playlistURL` TEXT DEFAULT '', `playlistIndex` INTEGER)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "format",
"columnName": "format",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "container",
"columnName": "container",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'Default'"
},
{
"fieldPath": "downloadSections",
"columnName": "downloadSections",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "allFormats",
"columnName": "allFormats",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadPath",
"columnName": "downloadPath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadSize",
"columnName": "downloadSize",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "playlistTitle",
"columnName": "playlistTitle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "audioPreferences",
"columnName": "audioPreferences",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "videoPreferences",
"columnName": "videoPreferences",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "extraCommands",
"columnName": "extraCommands",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "customFileNameTemplate",
"columnName": "customFileNameTemplate",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "SaveThumb",
"columnName": "SaveThumb",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'Queued'"
},
{
"fieldPath": "downloadStartTime",
"columnName": "downloadStartTime",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "logID",
"columnName": "logID",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "playlistURL",
"columnName": "playlistURL",
"affinity": "TEXT",
"notNull": false,
"defaultValue": "''"
},
{
"fieldPath": "playlistIndex",
"columnName": "playlistIndex",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "commandTemplates",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `useAsExtraCommand` INTEGER NOT NULL DEFAULT 0, `useAsExtraCommandAudio` INTEGER NOT NULL DEFAULT 1, `useAsExtraCommandVideo` INTEGER NOT NULL DEFAULT 1)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "useAsExtraCommand",
"columnName": "useAsExtraCommand",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "useAsExtraCommandAudio",
"columnName": "useAsExtraCommandAudio",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "1"
},
{
"fieldPath": "useAsExtraCommandVideo",
"columnName": "useAsExtraCommandVideo",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "1"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "searchHistory",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "query",
"columnName": "query",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "templateShortcuts",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `content` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "cookies",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "logs",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `format` TEXT NOT NULL, `downloadType` TEXT NOT NULL, `downloadTime` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "format",
"columnName": "format",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadType",
"columnName": "downloadType",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadTime",
"columnName": "downloadTime",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "terminalDownloads",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `command` TEXT NOT NULL, `log` TEXT DEFAULT '')",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "command",
"columnName": "command",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "log",
"columnName": "log",
"affinity": "TEXT",
"notNull": false,
"defaultValue": "''"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "sources",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `downloadItemTemplate` TEXT NOT NULL, `everyNr` INTEGER NOT NULL, `everyCategory` TEXT NOT NULL, `everyTime` INTEGER NOT NULL, `weeklyConfig` TEXT, `monthlyConfig` TEXT, `status` TEXT NOT NULL, `startsTime` INTEGER NOT NULL, `endsDate` INTEGER NOT NULL DEFAULT 0, `endsAfterCount` INTEGER NOT NULL DEFAULT 0, `runCount` INTEGER NOT NULL DEFAULT 0, `getOnlyNewUploads` INTEGER NOT NULL DEFAULT 0, `retryMissingDownloads` INTEGER NOT NULL, `alreadyProcessedLinks` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadItemTemplate",
"columnName": "downloadItemTemplate",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "everyNr",
"columnName": "everyNr",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "everyCategory",
"columnName": "everyCategory",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "everyTime",
"columnName": "everyTime",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "weeklyConfig",
"columnName": "weeklyConfig",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "monthlyConfig",
"columnName": "monthlyConfig",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "startsTime",
"columnName": "startsTime",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "endsDate",
"columnName": "endsDate",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "endsAfterCount",
"columnName": "endsAfterCount",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "runCount",
"columnName": "runCount",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "getOnlyNewUploads",
"columnName": "getOnlyNewUploads",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "retryMissingDownloads",
"columnName": "retryMissingDownloads",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "alreadyProcessedLinks",
"columnName": "alreadyProcessedLinks",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6d3700c5756542e79e6368575533f6ed')"
]
}
}

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis package com.deniscerri.ytdl
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry

View file

@ -9,6 +9,7 @@
android:maxSdkVersion="32" /> android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission <uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
@ -18,10 +19,7 @@
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
android:name="android.permission.SCHEDULE_EXACT_ALARM"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<application <application
@ -50,6 +48,7 @@
android:exported="true" android:exported="true"
android:launchMode="singleTask" android:launchMode="singleTask"
android:windowSoftInputMode="adjustPan"> android:windowSoftInputMode="adjustPan">
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
</activity> </activity>
<activity <activity
@ -222,17 +221,20 @@
<data android:host="rutube.com" /> <data android:host="rutube.com" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".receiver.ShareFileActivity" android:name=".receiver.TransparentActivity"
android:configChanges="smallestScreenSize|layoutDirection|locale|orientation|screenSize" android:configChanges="smallestScreenSize|layoutDirection|locale|orientation|screenSize"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:exported="true" android:exported="true"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:theme="@style/Theme.BottomSheet"> android:theme="@style/Theme.BottomSheet">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".ui.more.settings.SettingsActivity" android:name=".ui.more.settings.SettingsActivity"
android:configChanges="smallestScreenSize|layoutDirection|orientation|screenSize" android:configChanges="smallestScreenSize|layoutDirection|orientation|screenSize"
@ -280,6 +282,7 @@
android:targetActivity=".MainActivity" android:targetActivity=".MainActivity"
android:windowSoftInputMode="adjustPan" android:windowSoftInputMode="adjustPan"
android:exported="true"> android:exported="true">
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@ -302,6 +305,7 @@
android:launchMode="singleTask" android:launchMode="singleTask"
android:targetActivity=".MainActivity" android:targetActivity=".MainActivity"
android:windowSoftInputMode="adjustPan"> android:windowSoftInputMode="adjustPan">
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@ -323,6 +327,7 @@
android:launchMode="singleTask" android:launchMode="singleTask"
android:targetActivity=".MainActivity" android:targetActivity=".MainActivity"
android:windowSoftInputMode="adjustPan"> android:windowSoftInputMode="adjustPan">
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@ -351,9 +356,6 @@
<receiver android:name=".receiver.CancelDownloadNotificationReceiver" /> <receiver android:name=".receiver.CancelDownloadNotificationReceiver" />
<receiver android:name=".receiver.CancelWorkReceiver" /> <receiver android:name=".receiver.CancelWorkReceiver" />
<receiver android:name=".receiver.PauseDownloadNotificationReceiver" /> <receiver android:name=".receiver.PauseDownloadNotificationReceiver" />
<receiver android:name=".receiver.downloadAlarmReceivers.AlarmStartReceiver" />
<receiver android:name=".receiver.downloadAlarmReceivers.AlarmStopReceiver" />
<receiver android:name=".receiver.ObserveAlarmReceiver" />
<activity <activity
android:name=".receiver.ResumeActivity" android:name=".receiver.ResumeActivity"

View file

@ -1,12 +1,11 @@
package com.deniscerri.ytdlnis package com.deniscerri.ytdl
import android.app.Application import android.app.Application
import android.os.Looper import android.os.Looper
import android.widget.Toast import android.widget.Toast
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.util.CrashListener import com.deniscerri.ytdl.util.NotificationUtil
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.yausername.aria2c.Aria2c import com.yausername.aria2c.Aria2c
import com.yausername.ffmpeg.FFmpeg import com.yausername.ffmpeg.FFmpeg
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis package com.deniscerri.ytdl
import android.Manifest import android.Manifest
import android.app.ActionBar.LayoutParams import android.app.ActionBar.LayoutParams
@ -35,18 +35,18 @@ import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel import com.deniscerri.ytdl.database.viewmodel.CookieViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.ui.BaseActivity import com.deniscerri.ytdl.ui.BaseActivity
import com.deniscerri.ytdlnis.ui.HomeFragment import com.deniscerri.ytdl.ui.HomeFragment
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity import com.deniscerri.ytdl.ui.more.settings.SettingsActivity
import com.deniscerri.ytdlnis.util.CrashListener import com.deniscerri.ytdl.util.CrashListener
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdlnis.util.ThemeUtil import com.deniscerri.ytdl.util.ThemeUtil
import com.deniscerri.ytdlnis.util.UpdateUtil import com.deniscerri.ytdl.util.UpdateUtil
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.elevation.SurfaceColors import com.google.android.material.elevation.SurfaceColors
@ -59,7 +59,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -101,6 +100,8 @@ class MainActivity : BaseActivity() {
} }
} }
askPermissions() askPermissions()
checkUpdate() checkUpdate()
@ -412,6 +413,24 @@ class MainActivity : BaseActivity() {
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
}else if (action == Intent.ACTION_VIEW){
when(intent.getStringExtra("destination")){
"Downloads" -> {
navController.navigate(R.id.historyFragment)
}
"Queue" -> {
navController.navigate(R.id.downloadQueueMainFragment)
}
"Search" -> {
val bundle = Bundle()
bundle.putBoolean("search", true)
navController.popBackStack(R.id.homeFragment, true)
navController.navigate(
R.id.homeFragment,
bundle
)
}
}
} }
} }
@ -425,88 +444,6 @@ class MainActivity : BaseActivity() {
} }
} }
private fun askPermissions() {
val permissions = arrayListOf<String>()
if (!checkFilePermission()) {
if (Build.VERSION.SDK_INT >= 33){
permissions.add(Manifest.permission.READ_MEDIA_AUDIO)
permissions.add(Manifest.permission.READ_MEDIA_VIDEO)
}else{
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (!checkNotificationPermission()){
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
}
}
if (permissions.isNotEmpty()){
ActivityCompat.requestPermissions(
this,
permissions.toTypedArray(),
1
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
for (i in permissions.indices) {
if (permissions.contains(Manifest.permission.POST_NOTIFICATIONS)) continue
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
createPermissionRequestDialog()
}
}
}
private fun exit() {
finishAffinity()
exitProcess(0)
}
private fun checkFilePermission(): Boolean {
return if(Build.VERSION.SDK_INT >= 33){
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_AUDIO)
== PackageManager.PERMISSION_GRANTED) &&
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO)
== PackageManager.PERMISSION_GRANTED)
}else{
(ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) &&
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED)
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun checkNotificationPermission(): Boolean {
return (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED)
}
private fun createPermissionRequestDialog() {
val dialog = MaterialAlertDialogBuilder(this)
dialog.setTitle(getString(R.string.warning))
dialog.setMessage(getString(R.string.request_permission_desc))
dialog.setOnCancelListener { exit() }
dialog.setNegativeButton(getString(R.string.exit_app)) { _: DialogInterface?, _: Int -> exit() }
dialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null)
)
startActivity(intent)
exitProcess(0)
}
dialog.show()
}
companion object { companion object {
private const val TAG = "MainActivity" private const val TAG = "MainActivity"
} }

View file

@ -1,12 +1,14 @@
package com.deniscerri.ytdlnis.database package com.deniscerri.ytdl.database
import androidx.room.TypeConverter import androidx.room.TypeConverter
import com.deniscerri.ytdlnis.database.models.AudioPreferences import com.deniscerri.ytdl.database.models.AudioPreferences
import com.deniscerri.ytdlnis.database.models.ChapterItem import com.deniscerri.ytdl.database.models.ChapterItem
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdl.database.models.Format
import com.deniscerri.ytdlnis.database.models.VideoPreferences import com.deniscerri.ytdl.database.models.VideoPreferences
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesMonthlyConfig
import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesWeeklyConfig
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.google.gson.Gson import com.google.gson.Gson
@ -73,4 +75,17 @@ class Converters {
@TypeConverter @TypeConverter
fun stringtoMutableListofStrings(s: String) = Gson().fromJson(s, Array<String>::class.java).toMutableList() fun stringtoMutableListofStrings(s: String) = Gson().fromJson(s, Array<String>::class.java).toMutableList()
@TypeConverter
fun observeSourcesWeeklyConfigToString(c: ObserveSourcesWeeklyConfig) = Gson().toJson(c)
@TypeConverter
fun stringToObserveSourcesWeeklyConfig(s: String) = Gson().fromJson(s, ObserveSourcesWeeklyConfig::class.java)
@TypeConverter
fun observeSourcesMonthlyConfigToString(c: ObserveSourcesMonthlyConfig) = Gson().toJson(c)
@TypeConverter
fun stringToObserveSourcesMonthlyConfig(s: String) = Gson().fromJson(s, ObserveSourcesMonthlyConfig::class.java)
} }

View file

@ -1,30 +1,31 @@
package com.deniscerri.ytdlnis.database package com.deniscerri.ytdl.database
import android.content.Context import android.content.Context
import androidx.room.AutoMigration import androidx.room.AutoMigration
import androidx.room.Database import androidx.room.Database
import androidx.room.DeleteTable
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters import androidx.room.TypeConverters
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao import com.deniscerri.ytdl.database.dao.CommandTemplateDao
import com.deniscerri.ytdlnis.database.dao.CookieDao import com.deniscerri.ytdl.database.dao.CookieDao
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdl.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.dao.HistoryDao import com.deniscerri.ytdl.database.dao.HistoryDao
import com.deniscerri.ytdlnis.database.dao.LogDao import com.deniscerri.ytdl.database.dao.LogDao
import com.deniscerri.ytdlnis.database.dao.ObserveSourcesDao import com.deniscerri.ytdl.database.dao.ObserveSourcesDao
import com.deniscerri.ytdlnis.database.dao.ResultDao import com.deniscerri.ytdl.database.dao.ResultDao
import com.deniscerri.ytdlnis.database.dao.SearchHistoryDao import com.deniscerri.ytdl.database.dao.SearchHistoryDao
import com.deniscerri.ytdlnis.database.dao.TerminalDao import com.deniscerri.ytdl.database.dao.TerminalDao
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.CookieItem import com.deniscerri.ytdl.database.models.CookieItem
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdl.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.models.LogItem import com.deniscerri.ytdl.database.models.LogItem
import com.deniscerri.ytdlnis.database.models.ObserveSourcesItem import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.models.SearchHistoryItem import com.deniscerri.ytdl.database.models.SearchHistoryItem
import com.deniscerri.ytdlnis.database.models.TemplateShortcut import com.deniscerri.ytdl.database.models.TemplateShortcut
import com.deniscerri.ytdlnis.database.models.TerminalItem import com.deniscerri.ytdl.database.models.TerminalItem
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
@Database( @Database(
@ -40,7 +41,7 @@ import com.deniscerri.ytdlnis.database.models.TerminalItem
TerminalItem::class, TerminalItem::class,
ObserveSourcesItem::class ObserveSourcesItem::class
], ],
version = 15, version = 16,
autoMigrations = [ autoMigrations = [
AutoMigration (from = 1, to = 2), AutoMigration (from = 1, to = 2),
AutoMigration (from = 2, to = 3), AutoMigration (from = 2, to = 3),
@ -56,6 +57,7 @@ import com.deniscerri.ytdlnis.database.models.TerminalItem
AutoMigration (from = 12, to = 13), AutoMigration (from = 12, to = 13),
// AutoMigration (from = 13, to = 14) MANUALLY HANDLED // AutoMigration (from = 13, to = 14) MANUALLY HANDLED
AutoMigration (from = 14, to = 15), AutoMigration (from = 14, to = 15),
AutoMigration (from = 15, to = 16, spec = Migrations.resetObserveSources::class)
] ]
) )
abstract class DBManager : RoomDatabase(){ abstract class DBManager : RoomDatabase(){

View file

@ -1,7 +1,10 @@
package com.deniscerri.ytdlnis.database package com.deniscerri.ytdl.database
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.room.DeleteTable
import androidx.room.migration.AutoMigrationSpec
import androidx.room.migration.Migration import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
object Migrations { object Migrations {
@ -23,6 +26,18 @@ object Migrations {
} }
) )
@DeleteTable.Entries(
DeleteTable(
tableName = "observeSources"
)
)
class resetObserveSources : AutoMigrationSpec {
@Override
override fun onPostMigrate(db: SupportSQLiteDatabase) {
// Invoked once auto migration is done
}
}
} }

View file

@ -1,12 +1,12 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.TemplateShortcut import com.deniscerri.ytdl.database.models.TemplateShortcut
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,11 +1,11 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.deniscerri.ytdlnis.database.models.CookieItem import com.deniscerri.ytdl.database.models.CookieItem
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.room.Dao import androidx.room.Dao
@ -9,9 +9,9 @@ import androidx.room.RewriteQueriesToDropUnusedColumns
import androidx.room.Transaction import androidx.room.Transaction
import androidx.room.Update import androidx.room.Update
import androidx.room.Upsert import androidx.room.Upsert
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdl.database.models.DownloadItemSimple
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdl.database.models.Format
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,11 +1,11 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdl.database.models.HistoryItem
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
@ -6,7 +6,7 @@ import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Transaction import androidx.room.Transaction
import androidx.room.Update import androidx.room.Update
import com.deniscerri.ytdlnis.database.models.LogItem import com.deniscerri.ytdl.database.models.LogItem
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,37 +1,37 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.deniscerri.ytdlnis.database.models.ObserveSourcesItem import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface ObserveSourcesDao { interface ObserveSourcesDao {
@Query("SELECT * FROM observeSources ORDER BY id DESC") @Query("SELECT * FROM sources ORDER BY id DESC")
fun getAllSources() : List<ObserveSourcesItem> fun getAllSources() : List<ObserveSourcesItem>
@Query("SELECT * FROM observeSources WHERE url = :url LIMIT 1") @Query("SELECT * FROM sources WHERE url = :url LIMIT 1")
fun getByURL(url: String) : ObserveSourcesItem fun getByURL(url: String) : ObserveSourcesItem
@Query("SELECT * FROM observeSources WHERE id = :id LIMIT 1") @Query("SELECT * FROM sources WHERE id = :id LIMIT 1")
fun getByID(id: Long) : ObserveSourcesItem fun getByID(id: Long) : ObserveSourcesItem
@Query("SELECT * FROM observeSources ORDER BY id DESC") @Query("SELECT * FROM sources ORDER BY id DESC")
fun getAllSourcesFlow() : Flow<List<ObserveSourcesItem>> fun getAllSourcesFlow() : Flow<List<ObserveSourcesItem>>
@Query("SELECT EXISTS(SELECT * FROM observeSources WHERE url=:url LIMIT 1)") @Query("SELECT EXISTS(SELECT * FROM sources WHERE url=:url LIMIT 1)")
fun checkIfExistsWithSameURL(url: String) : Boolean fun checkIfExistsWithSameURL(url: String) : Boolean
@Insert(onConflict = OnConflictStrategy.IGNORE) @Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(item: ObserveSourcesItem) : Long suspend fun insert(item: ObserveSourcesItem) : Long
@Query("DELETE FROM observeSources") @Query("DELETE FROM sources")
suspend fun deleteAll() suspend fun deleteAll()
@Query("DELETE FROM observeSources WHERE id=:itemId") @Query("DELETE FROM sources WHERE id=:itemId")
suspend fun delete(itemId: Long) suspend fun delete(itemId: Long)
@Update(onConflict = OnConflictStrategy.REPLACE) @Update(onConflict = OnConflictStrategy.REPLACE)

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
@ -6,7 +6,7 @@ import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Transaction import androidx.room.Transaction
import androidx.room.Update import androidx.room.Update
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,10 +1,10 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import com.deniscerri.ytdlnis.database.models.SearchHistoryItem import com.deniscerri.ytdl.database.models.SearchHistoryItem
@Dao @Dao
interface SearchHistoryDao { interface SearchHistoryDao {

View file

@ -1,11 +1,11 @@
package com.deniscerri.ytdlnis.database.dao package com.deniscerri.ytdl.database.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Transaction import androidx.room.Transaction
import com.deniscerri.ytdlnis.database.models.TerminalItem import com.deniscerri.ytdl.database.models.TerminalItem
import com.deniscerri.ytdlnis.util.Extensions.appendLineToLog import com.deniscerri.ytdl.util.Extensions.appendLineToLog
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import android.os.Parcelable import android.os.Parcelable
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import android.os.Parcelable import android.os.Parcelable
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey

View file

@ -1,10 +1,10 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import android.os.Parcelable import android.os.Parcelable
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@Entity(tableName = "downloads") @Entity(tableName = "downloads")

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import android.os.Parcelable import android.os.Parcelable
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import java.util.Date import java.util.Date

View file

@ -1,9 +1,9 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
@Entity(tableName = "history") @Entity(tableName = "history")
data class HistoryItem( data class HistoryItem(

View file

@ -1,8 +1,8 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
@Entity(tableName = "logs") @Entity(tableName = "logs")
data class LogItem( data class LogItem(

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import android.os.Parcelable import android.os.Parcelable
import androidx.room.ColumnInfo import androidx.room.ColumnInfo

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
data class SearchSuggestionItem( data class SearchSuggestionItem(
var text: String, var text: String,

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models
import android.os.Parcelable import android.os.Parcelable
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize

View file

@ -1,14 +1,15 @@
package com.deniscerri.ytdlnis.database.models package com.deniscerri.ytdl.database.models.observeSources
import android.os.Parcelable import android.os.Parcelable
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.deniscerri.ytdlnis.database.repository.ObserveSourcesRepository import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import java.time.Month import java.time.Month
@Entity(tableName = "observeSources") @Entity(tableName = "sources")
@Parcelize @Parcelize
data class ObserveSourcesItem( data class ObserveSourcesItem(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
@ -16,14 +17,15 @@ data class ObserveSourcesItem(
var name: String, var name: String,
var url: String, var url: String,
var downloadItemTemplate: DownloadItem, var downloadItemTemplate: DownloadItem,
var status: ObserveSourcesRepository.SourceStatus,
var everyNr: Int, var everyNr: Int,
var everyCategory: ObserveSourcesRepository.EveryCategory, var everyCategory: ObserveSourcesRepository.EveryCategory,
val everyWeekDay: List<String>,
val everyMonthDay: Int,
val everyTime: Long, val everyTime: Long,
var weeklyConfig: ObserveSourcesWeeklyConfig?,
var monthlyConfig: ObserveSourcesMonthlyConfig?,
var status: ObserveSourcesRepository.SourceStatus,
var startsTime: Long, var startsTime: Long,
val startsMonth: Month,
@ColumnInfo(defaultValue = "0") @ColumnInfo(defaultValue = "0")
var endsDate: Long, var endsDate: Long,
@ColumnInfo(defaultValue = "0") @ColumnInfo(defaultValue = "0")

View file

@ -0,0 +1,11 @@
package com.deniscerri.ytdl.database.models.observeSources
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.time.Month
@Parcelize
data class ObserveSourcesMonthlyConfig(
var everyMonthDay: Int,
var startsMonth: Int
) : Parcelable

View file

@ -0,0 +1,9 @@
package com.deniscerri.ytdl.database.models.observeSources
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class ObserveSourcesWeeklyConfig(
var weekDays: List<Int>
) : Parcelable

View file

@ -1,9 +1,9 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao import com.deniscerri.ytdl.database.dao.CommandTemplateDao
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.TemplateShortcut import com.deniscerri.ytdl.database.models.TemplateShortcut
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
class CommandTemplateRepository(private val commandDao: CommandTemplateDao) { class CommandTemplateRepository(private val commandDao: CommandTemplateDao) {

View file

@ -1,7 +1,7 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import com.deniscerri.ytdlnis.database.dao.CookieDao import com.deniscerri.ytdl.database.dao.CookieDao
import com.deniscerri.ytdlnis.database.models.CookieItem import com.deniscerri.ytdl.database.models.CookieItem
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
class CookieRepository(private val cookieDao: CookieDao) { class CookieRepository(private val cookieDao: CookieDao) {

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
@ -16,14 +16,14 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.await import androidx.work.await
import com.deniscerri.ytdlnis.App import com.deniscerri.ytdl.App
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdl.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdl.database.models.DownloadItemSimple
import com.deniscerri.ytdlnis.util.Extensions.toListString import com.deniscerri.ytdl.util.Extensions.toListString
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdlnis.work.DownloadWorker import com.deniscerri.ytdl.work.DownloadWorker
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import java.io.File import java.io.File

View file

@ -1,9 +1,9 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import com.deniscerri.ytdlnis.database.DBManager.SORTING import com.deniscerri.ytdl.database.DBManager.SORTING
import com.deniscerri.ytdlnis.database.dao.HistoryDao import com.deniscerri.ytdl.database.dao.HistoryDao
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdl.database.models.HistoryItem
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest

View file

@ -1,8 +1,8 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import com.deniscerri.ytdlnis.database.dao.LogDao import com.deniscerri.ytdl.database.dao.LogDao
import com.deniscerri.ytdlnis.database.models.LogItem import com.deniscerri.ytdl.database.models.LogItem
import com.deniscerri.ytdlnis.util.Extensions.appendLineToLog import com.deniscerri.ytdl.util.Extensions.appendLineToLog
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
class LogRepository(private val logDao: LogDao) { class LogRepository(private val logDao: LogDao) {

View file

@ -0,0 +1,61 @@
package com.deniscerri.ytdl.database.repository
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.dao.ObserveSourcesDao
import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
import kotlinx.coroutines.flow.Flow
class ObserveSourcesRepository(private val observeSourcesDao: ObserveSourcesDao) {
val items : Flow<List<ObserveSourcesItem>> = observeSourcesDao.getAllSourcesFlow()
enum class SourceStatus {
ACTIVE, STOPPED
}
enum class EveryCategory {
HOUR, DAY, WEEK, MONTH
}
companion object {
val everyCategoryName = mapOf(
EveryCategory.HOUR to R.string.hour,
EveryCategory.DAY to R.string.day,
EveryCategory.WEEK to R.string.week,
EveryCategory.MONTH to R.string.month
)
}
fun getAll() : List<ObserveSourcesItem> {
return observeSourcesDao.getAllSources()
}
fun getByURL(url: String) : ObserveSourcesItem {
return observeSourcesDao.getByURL(url)
}
fun getByID(id: Long) : ObserveSourcesItem {
return observeSourcesDao.getByID(id)
}
suspend fun insert(item: ObserveSourcesItem) : Long{
if (!observeSourcesDao.checkIfExistsWithSameURL(item.url)){
return observeSourcesDao.insert(item)
}
return -1
}
suspend fun delete(item: ObserveSourcesItem){
observeSourcesDao.delete(item.id)
}
suspend fun deleteAll(){
observeSourcesDao.deleteAll()
}
suspend fun update(item: ObserveSourcesItem){
observeSourcesDao.update(item)
}
}

View file

@ -1,11 +1,11 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import android.content.Context import android.content.Context
import android.util.Patterns import android.util.Patterns
import com.deniscerri.ytdlnis.database.dao.ResultDao import com.deniscerri.ytdl.database.dao.ResultDao
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.InfoUtil
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import java.util.regex.Pattern import java.util.regex.Pattern

View file

@ -1,7 +1,7 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdl.database.repository
import com.deniscerri.ytdlnis.database.dao.SearchHistoryDao import com.deniscerri.ytdl.database.dao.SearchHistoryDao
import com.deniscerri.ytdlnis.database.models.SearchHistoryItem import com.deniscerri.ytdl.database.models.SearchHistoryItem
class SearchHistoryRepository(private val searchHistoryDao: SearchHistoryDao) { class SearchHistoryRepository(private val searchHistoryDao: SearchHistoryDao) {
fun getAll() : List<SearchHistoryItem> { fun getAll() : List<SearchHistoryItem> {

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.app.Application import android.app.Application
import android.content.ClipboardManager import android.content.ClipboardManager
@ -9,11 +9,11 @@ import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.CommandTemplateExport import com.deniscerri.ytdl.database.models.CommandTemplateExport
import com.deniscerri.ytdlnis.database.models.TemplateShortcut import com.deniscerri.ytdl.database.models.TemplateShortcut
import com.deniscerri.ytdlnis.database.repository.CommandTemplateRepository import com.deniscerri.ytdl.database.repository.CommandTemplateRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext

View file

@ -1,15 +1,11 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.R.attr.description
import android.R.attr.duration
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.ContentValues
import android.content.Context import android.content.Context
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteDatabase.OPEN_READONLY import android.database.sqlite.SQLiteDatabase.OPEN_READONLY
import android.database.sqlite.SQLiteDatabase.OPEN_READWRITE
import android.os.Environment import android.os.Environment
import android.util.Log import android.util.Log
import android.webkit.CookieManager import android.webkit.CookieManager
@ -17,13 +13,12 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.deniscerri.ytdlnis.BuildConfig import com.deniscerri.ytdl.BuildConfig
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.models.CookieItem import com.deniscerri.ytdl.database.models.CookieItem
import com.deniscerri.ytdlnis.database.repository.CookieRepository import com.deniscerri.ytdl.database.repository.CookieRepository
import com.deniscerri.ytdlnis.ui.more.WebViewActivity import com.deniscerri.ytdl.ui.more.WebViewActivity
import com.deniscerri.ytdlnis.util.Extensions.convertNetscapeToSetCookie import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdlnis.util.FileUtil
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Application import android.app.Application
@ -6,6 +6,7 @@ import android.content.SharedPreferences
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
@ -17,27 +18,27 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.deniscerri.ytdlnis.App import com.deniscerri.ytdl.App
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao import com.deniscerri.ytdl.database.dao.CommandTemplateDao
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdl.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.models.AudioPreferences import com.deniscerri.ytdl.database.models.AudioPreferences
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdl.database.models.DownloadItemSimple
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdl.database.models.Format
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdl.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.models.VideoPreferences import com.deniscerri.ytdl.database.models.VideoPreferences
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.repository.HistoryRepository import com.deniscerri.ytdl.database.repository.HistoryRepository
import com.deniscerri.ytdlnis.database.repository.ResultRepository import com.deniscerri.ytdl.database.repository.ResultRepository
import com.deniscerri.ytdlnis.ui.downloadcard.FormatTuple import com.deniscerri.ytdl.ui.downloadcard.FormatTuple
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.work.AlarmScheduler import com.deniscerri.ytdl.work.AlarmScheduler
import com.deniscerri.ytdlnis.work.UpdatePlaylistFormatsWorker import com.deniscerri.ytdl.work.UpdatePlaylistFormatsWorker
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -458,28 +459,61 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
} }
fun getPreferredAudioRequirements(): MutableList<(Format) -> Boolean> { fun getPreferredAudioRequirements(): MutableList<(Format) -> Int> {
val requirements: MutableList<(Format) -> Boolean> = mutableListOf() val requirements: MutableList<(Format) -> Int> = mutableListOf()
requirements.add {it: Format -> audioFormatIDPreference.contains(it.format_id)} requirements.add {it: Format -> if (audioFormatIDPreference.contains(it.format_id)) 10 else 0}
sharedPreferences.getString("audio_language", "")?.apply { sharedPreferences.getString("audio_language", "")?.apply {
if (this.isNotBlank()){ if (this.isNotBlank()){
requirements.add { it: Format -> it.lang?.contains(this) == true } requirements.add { it: Format -> if (it.lang?.contains(this) == true) 3 else 0 }
} }
} }
requirements.add {it: Format -> it.container == audioContainer } requirements.add {it: Format -> if ("^(${audioCodec}).+$".toRegex(RegexOption.IGNORE_CASE).matches(it.acodec)) 2 else 0}
requirements.add {it: Format -> "^(${audioCodec}).+$".toRegex(RegexOption.IGNORE_CASE).matches(it.acodec)} requirements.add {it: Format -> if (it.container == audioContainer) 1 else 0 }
return requirements return requirements
} }
fun getPreferredVideoRequirements(): MutableList<(Format) -> Boolean> { //requirement and importance
val requirements: MutableList<(Format) -> Boolean> = mutableListOf() @SuppressLint("RestrictedApi")
requirements.add { it: Format -> formatIDPreference.contains(it.format_id) } fun getPreferredVideoRequirements(): MutableList<(Format) -> Int> {
requirements.add { it: Format -> if (videoContainer == "mp4") it.container.equals("mpeg_4", true) else it.container.equals(videoContainer, true)} val requirements: MutableList<(Format) -> Int> = mutableListOf()
requirements.add { it: Format -> it.format_note.contains(videoQualityPreference.split("_")[0].dropLast(1)) } //format id
requirements.add { it: Format -> "^(${videoCodec}).+$".toRegex(RegexOption.IGNORE_CASE).matches(it.vcodec)} requirements.add { it: Format -> if (formatIDPreference.contains(it.format_id)) 20 else 0 }
requirements.add { it: Format -> it.acodec == "none" || it.acodec == "" } //resolutions
application.getStringArray(R.array.video_formats_values)
.filter { it.contains("_") }
.map{ it.split("_")[0].dropLast(1)
}.toMutableList().apply {
when(videoQualityPreference) {
"worst" -> {
requirements.add { it: Format -> if (it.format_note.contains("worst", ignoreCase = true)) (15) else 0 }
}
"best" -> {
requirements.add { it: Format -> if (it.format_note.contains("best", ignoreCase = true)) (15) else 0 }
}
else -> {
val preferenceIndex = this.indexOfFirst { videoQualityPreference.contains(it) }
val preference = this[preferenceIndex]
for(i in 0..preferenceIndex){
removeAt(0)
}
add(0, preference)
forEachIndexed { index, res ->
requirements.add { it: Format -> if (it.format_note.contains(res, ignoreCase = true)) (15 - index - 1) else 0 }
}
}
}
}
requirements.add { it: Format -> if ("^(${videoCodec})(.+)?$".toRegex(RegexOption.IGNORE_CASE).matches(it.vcodec)) 5 else 0 }
requirements.add { it: Format -> if (it.acodec == "none" || it.acodec == "") 1 else 0 }
requirements.add { it: Format ->
if (videoContainer == "mp4")
if (it.container.equals("mpeg_4", true)) 1 else 0
else
if (it.container.equals(videoContainer, true)) 1 else 0
}
return requirements return requirements
} }
@ -490,7 +524,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
try { try {
val theFormats = formats.filter { it.vcodec.isBlank() || it.vcodec == "none" } val theFormats = formats.filter { it.vcodec.isBlank() || it.vcodec == "none" }
val requirements = getPreferredAudioRequirements() val requirements = getPreferredAudioRequirements()
theFormats.maxByOrNull { f -> requirements.count{req -> req(f)} } ?: throw Exception() theFormats.maxByOrNull { f -> requirements.sumOf{ req -> req(f)} } ?: throw Exception()
}catch (e: Exception){ }catch (e: Exception){
bestAudioFormat bestAudioFormat
} }
@ -500,14 +534,25 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
Type.video -> { Type.video -> {
return cloneFormat( return cloneFormat(
try { try {
val theFormats = formats.filter { it.vcodec.isNotBlank() && it.vcodec != "null" }.ifEmpty { defaultVideoFormats.sortedByDescending { it.filesize } } val theFormats = formats.filter { it.vcodec.isNotBlank() && it.vcodec != "none" }.ifEmpty {
defaultVideoFormats.sortedByDescending { it.filesize }
}
when (videoQualityPreference) { when (videoQualityPreference) {
"worst" -> { "worst" -> {
theFormats.last() theFormats.last()
} }
else /*best*/ -> { else /*best*/ -> {
val requirements = getPreferredVideoRequirements() val requirements = getPreferredVideoRequirements()
theFormats.maxByOrNull { f -> requirements.count{ req -> req(f)} } ?: throw Exception() theFormats.run {
if (sharedPreferences.getBoolean("prefer_smaller_formats", false)){
sortedBy { it.filesize }.maxByOrNull { f -> requirements.sumOf { req -> req(f) } } ?: throw Exception()
}else{
sortedByDescending { it.filesize }.maxByOrNull { f ->
val summ = requirements.sumOf { req -> req(f) }
summ
} ?: throw Exception()
}
}
} }
} }
}catch (e: Exception){ }catch (e: Exception){
@ -828,7 +873,9 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
suspend fun updateProcessingFormat(selectedFormats: List<FormatTuple>): List<Long> { suspend fun updateProcessingFormat(selectedFormats: List<FormatTuple>): List<Long> {
val items = repository.getProcessingDownloads() val items = repository.getProcessingDownloads()
items.forEachIndexed { index, i -> items.forEachIndexed { index, i ->
i.format = selectedFormats[index].format selectedFormats[index].format?.apply {
i.format = this
}
if (i.type == Type.video) selectedFormats[index].audioFormats?.map { it.format_id }?.let { i.videoPreferences.audioFormatIDs.addAll(it) } if (i.type == Type.video) selectedFormats[index].audioFormats?.map { it.format_id }?.let { i.videoPreferences.audioFormatIDs.addAll(it) }
repository.update(i) repository.update(i)
} }

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
@ -7,11 +7,11 @@ import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.DBManager.SORTING import com.deniscerri.ytdl.database.DBManager.SORTING
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdl.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.repository.HistoryRepository import com.deniscerri.ytdl.database.repository.HistoryRepository
import com.deniscerri.ytdlnis.database.repository.HistoryRepository.HistorySortType import com.deniscerri.ytdl.database.repository.HistoryRepository.HistorySortType
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View file

@ -1,14 +1,14 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.models.LogItem import com.deniscerri.ytdl.database.models.LogItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.repository.LogRepository import com.deniscerri.ytdl.database.repository.LogRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View file

@ -0,0 +1,147 @@
package com.deniscerri.ytdl.database.viewmodel
import android.app.Application
import android.content.SharedPreferences
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import androidx.work.Constraints
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository
import com.deniscerri.ytdl.work.ObserveSourceWorker
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Calendar
import java.util.concurrent.TimeUnit
class ObserveSourcesViewModel(private val application: Application) : AndroidViewModel(application) {
private val repository: ObserveSourcesRepository
val items: LiveData<List<ObserveSourcesItem>>
private val workManager : WorkManager
private val preferences : SharedPreferences
init {
val dao = DBManager.getInstance(application).observeSourcesDao
repository = ObserveSourcesRepository(dao)
items = repository.items.asLiveData()
workManager = WorkManager.getInstance(application)
preferences = PreferenceManager.getDefaultSharedPreferences(application)
}
fun getAll(): List<ObserveSourcesItem> {
return repository.getAll()
}
fun getByURL(url: String) : ObserveSourcesItem {
return repository.getByURL(url)
}
fun getByID(id: Long) : ObserveSourcesItem {
return repository.getByID(id)
}
suspend fun insert(item: ObserveSourcesItem) : Long {
if (item.id > 0) {
repository.update(item)
observeTask(item)
return item.id
}
val id = repository.insert(item)
item.id = id
if (id > 0) observeTask(item)
return id
}
fun delete(item: ObserveSourcesItem) = viewModelScope.launch(Dispatchers.IO) {
runCatching { cancelObservationTaskByID(item.id) }
repository.delete(item)
}
fun deleteAll() = viewModelScope.launch(Dispatchers.IO) {
getAll().forEach {
runCatching { cancelObservationTaskByID(it.id) }
}
repository.deleteAll()
}
suspend fun update(item: ObserveSourcesItem) {
repository.update(item)
}
private fun cancelObservationTaskByID(id: Long){
workManager.cancelAllWorkByTag(id.toString())
}
private fun observeTask(it: ObserveSourcesItem){
cancelObservationTaskByID(it.id)
Calendar.getInstance().apply {
timeInMillis = it.startsTime
val date = Calendar.getInstance()
set(Calendar.DAY_OF_MONTH, date.get(Calendar.DAY_OF_MONTH))
set(Calendar.MONTH, date.get(Calendar.MONTH))
set(Calendar.YEAR, date.get(Calendar.YEAR))
if (it.everyCategory != ObserveSourcesRepository.EveryCategory.HOUR){
val hourMin = Calendar.getInstance()
hourMin.timeInMillis = it.everyTime
set(Calendar.HOUR_OF_DAY, hourMin.get(Calendar.HOUR_OF_DAY))
set(Calendar.MINUTE, hourMin.get(Calendar.MINUTE))
}
when(it.everyCategory){
ObserveSourcesRepository.EveryCategory.HOUR -> {}
ObserveSourcesRepository.EveryCategory.DAY -> {}
ObserveSourcesRepository.EveryCategory.WEEK -> {
var weekDayNr = get(Calendar.DAY_OF_WEEK) - 1
if (weekDayNr == 0) weekDayNr = 7
val followingWeekDay = it.weeklyConfig?.weekDays?.firstOrNull { it >= weekDayNr }
if (followingWeekDay == null){
add(Calendar.DAY_OF_MONTH,
it.weeklyConfig?.weekDays?.minBy { it }?.plus((7 - weekDayNr)) ?: 0)
}else{
add(Calendar.DAY_OF_MONTH, followingWeekDay - weekDayNr)
}
}
ObserveSourcesRepository.EveryCategory.MONTH -> {
val currentMonthIndex = get(Calendar.MONTH)
if (it.monthlyConfig?.startsMonth != currentMonthIndex){
set(Calendar.MONTH, it.monthlyConfig?.startsMonth ?: 0)
if (timeInMillis < Calendar.getInstance().timeInMillis){
add(Calendar.YEAR, 1)
}
}
}
}
//schedule for next time
val workConstraints = Constraints.Builder()
val workRequest = OneTimeWorkRequestBuilder<ObserveSourceWorker>()
.addTag("observeSources")
.addTag(it.id.toString())
.setConstraints(workConstraints.build())
.setInitialDelay(System.currentTimeMillis() - timeInMillis, TimeUnit.MILLISECONDS)
.setInputData(Data.Builder().putLong("id", it.id).build())
workManager.enqueueUniqueWork(
"OBSERVE${it.id}",
ExistingWorkPolicy.REPLACE,
workRequest.build()
)
}
}
}

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.app.ActivityManager import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo import android.app.ActivityManager.RunningAppProcessInfo
@ -10,24 +10,22 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.App import com.deniscerri.ytdl.App
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdl.database.dao.ResultDao
import com.deniscerri.ytdlnis.database.dao.ResultDao import com.deniscerri.ytdl.database.models.Format
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.SearchHistoryItem
import com.deniscerri.ytdlnis.database.models.SearchHistoryItem import com.deniscerri.ytdl.database.repository.ResultRepository
import com.deniscerri.ytdlnis.database.repository.ResultRepository import com.deniscerri.ytdl.database.repository.SearchHistoryRepository
import com.deniscerri.ytdlnis.database.repository.SearchHistoryRepository import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.NotificationUtil
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDLException import com.yausername.youtubedl_android.YoutubeDLException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
@ -106,36 +104,42 @@ class ResultViewModel(private val application: Application) : AndroidViewModel(a
uiState.update {it.copy(processing = false)} uiState.update {it.copy(processing = false)}
} }
private suspend fun parseQueriesImpl(inputQueries: List<String>, onResult: (list: List<ResultItem?>) -> Unit) {
if (inputQueries.size > 1){
repository.itemCount.value = inputQueries.size
}
val resetResults = inputQueries.size == 1
uiState.update {it.copy(processing = true, errorMessage = null, actions = null)}
val res = mutableListOf<ResultItem?>()
inputQueries.forEach { inputQuery ->
try {
res.addAll(repository.getResultsFromSource(inputQuery, resetResults))
} catch (e: Exception) {
if (updateResultDataJob?.isCancelled == false || e is YoutubeDLException){
uiState.update {it.copy(
processing = false,
errorMessage = Pair(R.string.no_results, e.message.toString()),
actions = mutableListOf(Pair(R.string.copy_log, ResultAction.COPY_LOG))
)}
Log.e(tag, e.toString())
}
}
}
if (!isForegrounded() && inputQueries.size > 1){
notificationUtil.showQueriesFinished()
}
uiState.update {it.copy(processing = false)}
onResult(res)
}
suspend fun parseQueries(inputQueries: List<String>, onResult: (list: List<ResultItem?>) -> Unit) { suspend fun parseQueries(inputQueries: List<String>, onResult: (list: List<ResultItem?>) -> Unit) {
if (parsingQueries == null || parsingQueries?.isCancelled == true || parsingQueries?.isCompleted == true) { if (parsingQueries == null || parsingQueries?.isCancelled == true || parsingQueries?.isCompleted == true) {
parsingQueries = viewModelScope.launch(Dispatchers.IO) { parsingQueries = viewModelScope.launch(Dispatchers.IO) {
if (inputQueries.size > 1){ parseQueriesImpl(inputQueries) {
repository.itemCount.value = inputQueries.size onResult(it)
} }
val resetResults = inputQueries.size == 1
uiState.update {it.copy(processing = true, errorMessage = null, actions = null)}
val res = mutableListOf<ResultItem?>()
inputQueries.forEach { inputQuery ->
try {
res.addAll(repository.getResultsFromSource(inputQuery, resetResults))
} catch (e: Exception) {
if (updateResultDataJob?.isCancelled == false || e is YoutubeDLException){
uiState.update {it.copy(
processing = false,
errorMessage = Pair(R.string.no_results, e.message.toString()),
actions = mutableListOf(Pair(R.string.copy_log, ResultAction.COPY_LOG))
)}
Log.e(tag, e.toString())
}
}
}
if (!isForegrounded() && inputQueries.size > 1){
notificationUtil.showQueriesFinished()
}
uiState.update {it.copy(processing = false)}
onResult(res)
} }
}else{ }else{
onResult(listOf()) onResult(listOf())
@ -207,7 +211,7 @@ class ResultViewModel(private val application: Application) : AndroidViewModel(a
updateResultDataJob = viewModelScope.launch(Dispatchers.IO) { updateResultDataJob = viewModelScope.launch(Dispatchers.IO) {
updatingData.emit(true) updatingData.emit(true)
updatingData.value = true updatingData.value = true
parseQueries(listOf(res.url)){ result -> parseQueriesImpl(listOf(res.url)){ result ->
viewModelScope.launch(Dispatchers.IO){ viewModelScope.launch(Dispatchers.IO){
updatingData.emit(false) updatingData.emit(false)
updatingData.value = false updatingData.value = false
@ -216,7 +220,7 @@ class ResultViewModel(private val application: Application) : AndroidViewModel(a
} }
} }
updateResultDataJob?.start() //updateResultDataJob?.start()
updateResultDataJob?.invokeOnCompletion { updateResultDataJob?.invokeOnCompletion {
if (it != null){ if (it != null){
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
@ -230,7 +234,7 @@ class ResultViewModel(private val application: Application) : AndroidViewModel(a
} }
} }
suspend fun cancelUpdateItemData(){ suspend fun cancelUpdateItemData() = viewModelScope.launch(Dispatchers.IO) {
updateResultDataJob?.cancel(CancellationException()) updateResultDataJob?.cancel(CancellationException())
updatingData.emit(false) updatingData.emit(false)
updatingData.value = false updatingData.value = false
@ -238,7 +242,7 @@ class ResultViewModel(private val application: Application) : AndroidViewModel(a
updateResultData.value = null updateResultData.value = null
} }
suspend fun cancelUpdateFormatsItemData(){ suspend fun cancelUpdateFormatsItemData() = viewModelScope.launch(Dispatchers.IO) {
updatingFormats.emit(false) updatingFormats.emit(false)
updatingFormats.value = false updatingFormats.value = false
updateFormatsResultData.emit(null) updateFormatsResultData.emit(null)

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdl.database.viewmodel
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
@ -6,11 +6,11 @@ import androidx.work.Data
import androidx.work.ExistingWorkPolicy import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.dao.TerminalDao import com.deniscerri.ytdl.database.dao.TerminalDao
import com.deniscerri.ytdlnis.database.models.TerminalItem import com.deniscerri.ytdl.database.models.TerminalItem
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdl.util.NotificationUtil
import com.deniscerri.ytdlnis.work.TerminalDownloadWorker import com.deniscerri.ytdl.work.TerminalDownloadWorker
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View file

@ -1,11 +1,11 @@
package com.deniscerri.ytdlnis.receiver package com.deniscerri.ytdl.receiver
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdl.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.receiver package com.deniscerri.ytdl.receiver
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context

View file

@ -1,11 +1,11 @@
package com.deniscerri.ytdlnis.receiver package com.deniscerri.ytdl.receiver
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdl.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.receiver package com.deniscerri.ytdl.receiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -12,11 +12,11 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.ui.BaseActivity import com.deniscerri.ytdl.ui.BaseActivity
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdl.util.NotificationUtil
import com.deniscerri.ytdlnis.util.ThemeUtil import com.deniscerri.ytdl.util.ThemeUtil
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.receiver package com.deniscerri.ytdl.receiver
import android.Manifest import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
@ -8,6 +8,8 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
@ -15,6 +17,8 @@ import android.os.Bundle
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import android.util.Patterns import android.util.Patterns
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager import android.view.WindowManager
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
@ -26,13 +30,13 @@ import androidx.navigation.NavDestination
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdl.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel import com.deniscerri.ytdl.database.viewmodel.CookieViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.ui.BaseActivity import com.deniscerri.ytdl.ui.BaseActivity
import com.deniscerri.ytdlnis.util.ThemeUtil import com.deniscerri.ytdl.util.ThemeUtil
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -43,6 +47,7 @@ import kotlinx.coroutines.withContext
import kotlin.properties.Delegates import kotlin.properties.Delegates
import kotlin.system.exitProcess import kotlin.system.exitProcess
class ShareActivity : BaseActivity() { class ShareActivity : BaseActivity() {
lateinit var context: Context lateinit var context: Context
@ -63,20 +68,51 @@ class ShareActivity : BaseActivity() {
v.setPadding(0, 0, 0, 0) v.setPadding(0, 0, 0, 0)
insets insets
} }
window.run {
setBackgroundDrawable(ColorDrawable(0)) if (Settings.canDrawOverlays(this)){
setLayout( val params = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.MATCH_PARENT WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
},
PixelFormat.TRANSLUCENT
) )
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val wm = getSystemService(WINDOW_SERVICE) as WindowManager
setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
} else { val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) val myView: View = inflater.inflate(R.layout.activity_share, null)
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
wm.addView(myView, params)
// window.addFlags(
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
// or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
// or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
// )
//
// val params = window.attributes
// params.alpha = 0f
// window.attributes = params
// setContentView(R.layout.activity_share)
}else{
window.run {
setBackgroundDrawable(ColorDrawable(0))
setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
} else {
setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
}
} }
setContentView(R.layout.activity_share)
} }
setContentView(R.layout.activity_share)
context = baseContext context = baseContext
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
@ -175,75 +211,6 @@ class ShareActivity : BaseActivity() {
} }
} }
} }
private fun askPermissions() {
val permissions = arrayListOf<String>()
if (!checkFilePermission()) {
if (Build.VERSION.SDK_INT >= 33){
permissions.add(Manifest.permission.READ_MEDIA_AUDIO)
permissions.add(Manifest.permission.READ_MEDIA_VIDEO)
}else{
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
}
if (!checkNotificationPermission()){
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
}
if (permissions.isNotEmpty()){
ActivityCompat.requestPermissions(
this,
permissions.toTypedArray(),
1
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
for (i in permissions.indices) {
if (permissions.contains(Manifest.permission.POST_NOTIFICATIONS)) break
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
createPermissionRequestDialog()
}
}
}
private fun exit() {
finishAffinity()
exitProcess(0)
}
private fun checkFilePermission(): Boolean {
return (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED)
}
private fun checkNotificationPermission(): Boolean {
return (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED)
}
private fun createPermissionRequestDialog() {
val dialog = MaterialAlertDialogBuilder(this)
dialog.setTitle(getString(R.string.warning))
dialog.setMessage(getString(R.string.request_permission_desc))
dialog.setOnCancelListener { exit() }
dialog.setNegativeButton(getString(R.string.exit_app)) { _: DialogInterface?, _: Int -> exit() }
dialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null)
)
startActivity(intent)
exitProcess(0)
}
dialog.show()
}
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
startActivity(Intent(this, MainActivity::class.java)) startActivity(Intent(this, MainActivity::class.java))
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)

View file

@ -0,0 +1,85 @@
package com.deniscerri.ytdl.receiver
import android.content.Context
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdl.ui.BaseActivity
import com.deniscerri.ytdl.util.NotificationUtil
import com.deniscerri.ytdl.util.ThemeUtil
import com.deniscerri.ytdl.util.UiUtil
class TransparentActivity : BaseActivity() {
lateinit var context: Context
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeUtil.updateTheme(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { v, insets ->
v.setPadding(0, 0, 0, 0)
insets
}
if (Settings.canDrawOverlays(this)){
window.addFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
)
val params = window.attributes
params.alpha = 0f
window.attributes = params
setContentView(R.layout.activity_share)
}else{
window.run {
setBackgroundDrawable(ColorDrawable(0))
setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
} else {
setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
}
}
setContentView(R.layout.activity_share)
}
when(intent.getStringExtra("action")){
"NEW_TEMPLATE" -> newTemplate()
}
}
private fun newTemplate(){
val viewmodel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
UiUtil.showCommandTemplateCreationOrUpdatingSheet(
null, this, this, viewmodel,
newTemplate = {
Toast.makeText(this, R.string.ok,Toast.LENGTH_SHORT).show()
this.finishAffinity()
},
dismissed = {
this.finishAffinity()
}
)
}
}

View file

@ -0,0 +1,112 @@
package com.deniscerri.ytdl.ui
import android.Manifest
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.util.ThemeUtil
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.elevation.SurfaceColors
import kotlin.system.exitProcess
open class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
ThemeUtil.updateTheme(this)
window.navigationBarColor = SurfaceColors.SURFACE_2.getColor(this)
super.onCreate(savedInstanceState)
}
fun askPermissions() {
val permissions = arrayListOf<String>()
if (!checkFilePermission()) {
if (Build.VERSION.SDK_INT >= 33){
permissions.add(Manifest.permission.READ_MEDIA_AUDIO)
permissions.add(Manifest.permission.READ_MEDIA_VIDEO)
if (Build.VERSION.SDK_INT >= 34){
permissions.add(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
}
}else{
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (!checkNotificationPermission()){
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
}
}
if (permissions.isNotEmpty()){
ActivityCompat.requestPermissions(
this,
permissions.toTypedArray(),
1
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
for (i in permissions.indices) {
if (permissions.contains(Manifest.permission.POST_NOTIFICATIONS)) continue
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
createPermissionRequestDialog()
}
}
}
private fun checkFilePermission(): Boolean {
return if(Build.VERSION.SDK_INT >= 33){
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_AUDIO)
== PackageManager.PERMISSION_GRANTED) &&
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO)
== PackageManager.PERMISSION_GRANTED)
}else{
(ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) &&
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED)
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun checkNotificationPermission(): Boolean {
return (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED)
}
private fun createPermissionRequestDialog() {
val dialog = MaterialAlertDialogBuilder(this)
dialog.setTitle(getString(R.string.warning))
dialog.setMessage(getString(R.string.request_permission_desc))
dialog.setOnCancelListener { exit() }
dialog.setNegativeButton(getString(R.string.exit_app)) { _: DialogInterface?, _: Int -> exit() }
dialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null)
)
startActivity(intent)
exitProcess(0)
}
dialog.show()
}
private fun exit() {
finishAffinity()
exitProcess(0)
}
}

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui package com.deniscerri.ytdl.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -32,22 +32,20 @@ import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdl.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.models.SearchSuggestionItem import com.deniscerri.ytdl.database.models.SearchSuggestionItem
import com.deniscerri.ytdlnis.database.models.SearchSuggestionType import com.deniscerri.ytdl.database.models.SearchSuggestionType
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.ui.adapter.HomeAdapter
import com.deniscerri.ytdlnis.ui.adapter.HomeAdapter import com.deniscerri.ytdl.ui.adapter.SearchSuggestionsAdapter
import com.deniscerri.ytdlnis.ui.adapter.SearchSuggestionsAdapter import com.deniscerri.ytdl.util.Extensions.enableFastScroll
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.util.Extensions.toListString import com.deniscerri.ytdl.util.ThemeUtil
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.UiUtil
import com.deniscerri.ytdlnis.util.ThemeUtil
import com.deniscerri.ytdlnis.util.UiUtil
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
@ -218,6 +216,12 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, SearchSuggesti
inputQueries!!.addAll(argList) inputQueries!!.addAll(argList)
} }
if(arguments?.getBoolean("search") == true){
requireView().post {
searchBar?.performClick()
}
}
if (inputQueries != null) { if (inputQueries != null) {
lifecycleScope.launch(Dispatchers.IO){ lifecycleScope.launch(Dispatchers.IO){
resultViewModel.deleteAll() resultViewModel.deleteAll()

View file

@ -1,9 +1,8 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
@ -17,18 +16,17 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.Extensions.dp import com.deniscerri.ytdl.util.Extensions.dp
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator
import com.squareup.picasso.Picasso
class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder( class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(

View file

@ -1,8 +1,7 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
@ -16,16 +15,15 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator
import com.squareup.picasso.Picasso
class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadMinifiedAdapter.ViewHolder>(AsyncDifferConfig.Builder( class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadMinifiedAdapter.ViewHolder>(AsyncDifferConfig.Builder(
DIFF_CALLBACK DIFF_CALLBACK

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
@ -10,17 +10,16 @@ import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
class AlreadyExistsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<Pair<DownloadItem, Long?>, AlreadyExistsAdapter.ViewHolder>(AsyncDifferConfig.Builder( class AlreadyExistsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<Pair<DownloadItem, Long?>, AlreadyExistsAdapter.ViewHolder>(AsyncDifferConfig.Builder(

View file

@ -1,8 +1,7 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
@ -16,14 +15,13 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.squareup.picasso.Picasso
import java.util.Locale import java.util.Locale
class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder( class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder(

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.view.LayoutInflater import android.view.LayoutInflater
@ -9,9 +9,9 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.CookieItem import com.deniscerri.ytdl.database.models.CookieItem
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
class CookieAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<CookieItem?, CookieAdapter.ViewHolder>(AsyncDifferConfig.Builder( class CookieAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<CookieItem?, CookieAdapter.ViewHolder>(AsyncDifferConfig.Builder(

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -11,11 +11,11 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.LogItem import com.deniscerri.ytdl.database.models.LogItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import java.text.SimpleDateFormat import java.text.SimpleDateFormat

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -14,15 +14,14 @@ import androidx.paging.PagingDataAdapter
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdl.database.models.DownloadItemSimple
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.squareup.picasso.Picasso
class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter<DownloadItemSimple, GenericDownloadAdapter.ViewHolder>( class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter<DownloadItemSimple, GenericDownloadAdapter.ViewHolder>(
DIFF_CALLBACK DIFF_CALLBACK

View file

@ -1,9 +1,8 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.ColorMatrix import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter import android.graphics.ColorMatrixColorFilter
import android.os.Handler import android.os.Handler
@ -19,15 +18,14 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdl.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.squareup.picasso.Picasso
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -15,11 +15,11 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator

View file

@ -1,24 +1,22 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.os.Handler
import android.os.Looper
import android.text.format.DateFormat import android.text.format.DateFormat
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.ObserveSourcesItem import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
import com.deniscerri.ytdlnis.database.repository.ObserveSourcesRepository import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.calculateNextTime
import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
@ -78,34 +76,10 @@ class ObserveSourcesAdapter(onItemClickListener: OnItemClickListener, activity:
//INFO //INFO
val info = card.findViewById<Chip>(R.id.info) val info = card.findViewById<Chip>(R.id.info)
val nextTime = item.calculateNextTime()
val c = Calendar.getInstance() val c = Calendar.getInstance()
val hourMin = Calendar.getInstance() c.timeInMillis = nextTime
hourMin.timeInMillis = item.everyTime
c.set(Calendar.HOUR_OF_DAY, hourMin.get(Calendar.HOUR_OF_DAY))
c.set(Calendar.MINUTE, hourMin.get(Calendar.MINUTE))
when(item.everyCategory){
ObserveSourcesRepository.EveryCategory.DAY -> {
c.add(Calendar.DAY_OF_MONTH, item.everyNr)
}
ObserveSourcesRepository.EveryCategory.WEEK -> {
if(item.everyWeekDay.isEmpty()){
c.add(Calendar.DAY_OF_MONTH, 7 * item.everyNr)
}else{
val weekDayID = c.get(Calendar.DAY_OF_WEEK).toString()
val followingWeekDay = (item.everyWeekDay.firstOrNull { it.toInt() > weekDayID.toInt() } ?: item.everyWeekDay.minBy { it.toInt() }).toInt()
c.set(Calendar.DAY_OF_WEEK, followingWeekDay)
if (item.everyNr > 1){
c.add(Calendar.DAY_OF_MONTH, 7 * item.everyNr)
}
}
}
ObserveSourcesRepository.EveryCategory.MONTH -> {
c.add(Calendar.MONTH, item.everyNr)
c.set(Calendar.DAY_OF_MONTH, item.everyMonthDay)
}
}
val weekdays = DateFormatSymbols(Locale.getDefault()).shortWeekdays val weekdays = DateFormatSymbols(Locale.getDefault()).shortWeekdays
val text = "${weekdays[c.get(Calendar.DAY_OF_WEEK)]}, ${SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(c.timeInMillis)}" val text = "${weekdays[c.get(Calendar.DAY_OF_WEEK)]}, ${SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(c.timeInMillis)}"
info.text = text info.text = text
@ -169,12 +143,13 @@ class ObserveSourcesAdapter(onItemClickListener: OnItemClickListener, activity:
} }
override fun areContentsTheSame(oldItem: ObserveSourcesItem, newItem: ObserveSourcesItem): Boolean { override fun areContentsTheSame(oldItem: ObserveSourcesItem, newItem: ObserveSourcesItem): Boolean {
return oldItem.id == newItem.id && return oldItem.id == newItem.id
oldItem.name == newItem.name && && oldItem.name == newItem.name
oldItem.downloadItemTemplate == newItem.downloadItemTemplate && && oldItem.downloadItemTemplate == newItem.downloadItemTemplate
oldItem.status == newItem.status && && oldItem.status == newItem.status
oldItem.retryMissingDownloads == newItem.retryMissingDownloads && && oldItem.retryMissingDownloads == newItem.retryMissingDownloads
oldItem.runCount == newItem.runCount && oldItem.runCount == newItem.runCount
&& oldItem.everyCategory == newItem.everyCategory
} }
} }
} }

View file

@ -1,9 +1,8 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
@ -12,18 +11,16 @@ import android.view.ViewGroup
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.util.Extensions.loadThumbnail import com.deniscerri.ytdl.util.Extensions.loadThumbnail
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.squareup.picasso.Picasso
import java.util.* import java.util.*

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
@ -13,9 +13,9 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.SearchSuggestionItem import com.deniscerri.ytdl.database.models.SearchSuggestionItem
import com.deniscerri.ytdlnis.database.models.SearchSuggestionType import com.deniscerri.ytdl.database.models.SearchSuggestionType
class SearchSuggestionsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<SearchSuggestionItem, SearchSuggestionsAdapter.ViewHolder>(AsyncDifferConfig.Builder( class SearchSuggestionsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<SearchSuggestionItem, SearchSuggestionsAdapter.ViewHolder>(AsyncDifferConfig.Builder(

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -11,9 +11,9 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
class TemplatesAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<CommandTemplate?, TemplatesAdapter.ViewHolder>(AsyncDifferConfig.Builder( class TemplatesAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<CommandTemplate?, TemplatesAdapter.ViewHolder>(AsyncDifferConfig.Builder(

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.adapter package com.deniscerri.ytdl.ui.adapter
import android.app.Activity import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
@ -11,9 +11,9 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.TerminalItem import com.deniscerri.ytdl.database.models.TerminalItem
import com.deniscerri.ytdlnis.util.Extensions.popup import com.deniscerri.ytdl.util.Extensions.popup
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Dialog import android.app.Dialog
@ -16,18 +16,17 @@ import android.widget.*
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight import com.deniscerri.ytdl.util.Extensions.enableTextHighlight
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil import com.deniscerri.ytdl.util.UiUtil
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.*
class AddExtraCommandsDialog(private val item: DownloadItem?, private val callback: ExtraCommandsListener) : BottomSheetDialogFragment() { class AddExtraCommandsDialog(private val item: DownloadItem?, private val callback: ExtraCommandsListener) : BottomSheetDialogFragment() {

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.view.View import android.view.View
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Dialog import android.app.Dialog
@ -19,14 +19,14 @@ import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel.Type
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.util.UiUtil import com.deniscerri.ytdl.util.UiUtil
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -147,12 +147,16 @@ class ConfigureDownloadBottomSheetDialog(private var result: ResultItem, private
val snackTextView = snackbarView.findViewById<View>(com.google.android.material.R.id.snackbar_text) as TextView val snackTextView = snackbarView.findViewById<View>(com.google.android.material.R.id.snackbar_text) as TextView
snackTextView.maxLines = 9999999 snackTextView.maxLines = 9999999
s.setAction(R.string.new_template){ s.setAction(R.string.new_template){
UiUtil.showCommandTemplateCreationOrUpdatingSheet(item = null, context = requireActivity(), lifeCycle = this@ConfigureDownloadBottomSheetDialog, commandTemplateViewModel = commandTemplateViewModel){ UiUtil.showCommandTemplateCreationOrUpdatingSheet(
commandTemplateNr = 1 item = null, context = requireActivity(), lifeCycle = this@ConfigureDownloadBottomSheetDialog, commandTemplateViewModel = commandTemplateViewModel,
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true newTemplate = {
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 1f commandTemplateNr = 1
tabLayout.selectTab(tabLayout.getTabAt(2)) (tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true
} (tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 1f
tabLayout.selectTab(tabLayout.getTabAt(2))
},
dismissed = {}
)
} }
s.show() s.show()
}else if (tab.position == 1 && isAudioOnly){ }else if (tab.position == 1 && isAudioOnly){

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Dialog import android.app.Dialog
@ -25,14 +25,14 @@ import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.MergingMediaSource import androidx.media3.exoplayer.source.MergingMediaSource
import androidx.media3.ui.PlayerView import androidx.media3.ui.PlayerView
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.ChapterItem import com.deniscerri.ytdl.database.models.ChapterItem
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.util.Extensions.setTextAndRecalculateWidth import com.deniscerri.ytdl.util.Extensions.setTextAndRecalculateWidth
import com.deniscerri.ytdlnis.util.Extensions.toStringDuration import com.deniscerri.ytdl.util.Extensions.toStringDuration
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil import com.deniscerri.ytdl.util.UiUtil
import com.deniscerri.ytdlnis.util.VideoPlayerUtil import com.deniscerri.ytdl.util.VideoPlayerUtil
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -24,16 +24,16 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdl.database.models.Format
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel.Type
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil import com.deniscerri.ytdl.util.UiUtil
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -210,8 +210,10 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
UiUtil.populateFormatCard(requireContext(), formatCard, chosenFormat, null) UiUtil.populateFormatCard(requireContext(), formatCard, chosenFormat, null)
val listener = object : OnFormatClickListener { val listener = object : OnFormatClickListener {
override fun onFormatClick(item: List<FormatTuple>) { override fun onFormatClick(item: List<FormatTuple>) {
downloadItem.format = item.first().format item.first().format?.apply {
UiUtil.populateFormatCard(requireContext(), formatCard, item.first().format, null) downloadItem.format = this
UiUtil.populateFormatCard(requireContext(), formatCard, this, null)
}
} }
override fun onFormatsUpdated(allFormats: List<List<Format>>) { override fun onFormatsUpdated(allFormats: List<List<Format>>) {

View file

@ -1,8 +1,7 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Dialog import android.app.Dialog
import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.Configuration import android.content.res.Configuration
@ -20,11 +19,9 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.get
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.commitNow
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
@ -32,18 +29,18 @@ import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel.Type
import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.receiver.ShareActivity import com.deniscerri.ytdl.receiver.ShareActivity
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdl.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil import com.deniscerri.ytdl.util.UiUtil
import com.facebook.shimmer.ShimmerFrameLayout import com.facebook.shimmer.ShimmerFrameLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
@ -155,9 +152,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
shimmerLoading.setOnClickListener { shimmerLoading.setOnClickListener {
lifecycleScope.launch { lifecycleScope.launch {
withContext(Dispatchers.IO){ resultViewModel.cancelUpdateItemData()
resultViewModel.cancelUpdateItemData()
}
(updateItem.parent as LinearLayout).visibility = View.VISIBLE (updateItem.parent as LinearLayout).visibility = View.VISIBLE
} }
} }
@ -252,12 +247,18 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
val snackTextView = snackbarView.findViewById<View>(com.google.android.material.R.id.snackbar_text) as TextView val snackTextView = snackbarView.findViewById<View>(com.google.android.material.R.id.snackbar_text) as TextView
snackTextView.maxLines = 9999999 snackTextView.maxLines = 9999999
s.setAction(R.string.new_template){ s.setAction(R.string.new_template){
UiUtil.showCommandTemplateCreationOrUpdatingSheet(item = null, context = requireActivity(), lifeCycle = this@DownloadBottomSheetDialog, commandTemplateViewModel = commandTemplateViewModel){ UiUtil.showCommandTemplateCreationOrUpdatingSheet(
commandTemplateNr = 1 item = null, context = requireActivity(), lifeCycle = this@DownloadBottomSheetDialog, commandTemplateViewModel = commandTemplateViewModel,
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true newTemplate = {
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 1f commandTemplateNr = 1
tabLayout.selectTab(tabLayout.getTabAt(2)) (tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true
} (tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 1f
tabLayout.selectTab(tabLayout.getTabAt(2))
},
dismissed = {
}
)
} }
s.show() s.show()
}else if (tab.position == 1 && isAudioOnly){ }else if (tab.position == 1 && isAudioOnly){
@ -305,10 +306,8 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
scheduleBtn.setOnClickListener{ scheduleBtn.setOnClickListener{
UiUtil.showDatePicker(fragmentManager) { UiUtil.showDatePicker(fragmentManager) {
lifecycleScope.launch { lifecycleScope.launch {
withContext(Dispatchers.IO){ resultViewModel.cancelUpdateItemData()
resultViewModel.cancelUpdateItemData() resultViewModel.cancelUpdateFormatsItemData()
resultViewModel.cancelUpdateFormatsItemData()
}
} }
scheduleBtn.isEnabled = false scheduleBtn.isEnabled = false
@ -344,10 +343,8 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
} }
download!!.setOnClickListener { download!!.setOnClickListener {
lifecycleScope.launch { lifecycleScope.launch {
withContext(Dispatchers.IO){ resultViewModel.cancelUpdateItemData()
resultViewModel.cancelUpdateItemData() resultViewModel.cancelUpdateFormatsItemData()
resultViewModel.cancelUpdateFormatsItemData()
}
scheduleBtn.isEnabled = false scheduleBtn.isEnabled = false
download.isEnabled = false download.isEnabled = false
val item: DownloadItem = getDownloadItem() val item: DownloadItem = getDownloadItem()
@ -481,7 +478,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
isVisible = true isVisible = true
isClickable = true isClickable = true
setOnClickListener { setOnClickListener {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch {
resultViewModel.cancelUpdateFormatsItemData() resultViewModel.cancelUpdateFormatsItemData()
} }
} }
@ -493,7 +490,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
isVisible = true isVisible = true
isClickable = true isClickable = true
setOnClickListener { setOnClickListener {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch {
resultViewModel.cancelUpdateFormatsItemData() resultViewModel.cancelUpdateFormatsItemData()
} }
} }
@ -687,7 +684,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
} }
if (resultViewModel.updatingData.value) return if (resultViewModel.updatingData.value) return
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
resultViewModel.updateItemData(result) resultViewModel.updateItemData(result)
} }
} }

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdlnis.ui.downloadcard package com.deniscerri.ytdl.ui.downloadcard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
@ -23,17 +23,17 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdl.R
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdl.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdl.database.models.Format
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight import com.deniscerri.ytdl.util.Extensions.enableTextHighlight
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdlnis.util.UiUtil import com.deniscerri.ytdl.util.UiUtil
import com.deniscerri.ytdlnis.util.UiUtil.populateCommandCard import com.deniscerri.ytdl.util.UiUtil.populateCommandCard
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -218,24 +218,28 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
if (downloadItem.url.isEmpty()) 0 else 1, if (downloadItem.url.isEmpty()) 0 else 1,
shortcutCount, shortcutCount,
newTemplateClicked = { newTemplateClicked = {
UiUtil.showCommandTemplateCreationOrUpdatingSheet(null, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) { UiUtil.showCommandTemplateCreationOrUpdatingSheet(
templates.add(it) null, requireActivity(), viewLifecycleOwner, commandTemplateViewModel,
chosenCommandView.editText!!.setText(it.content) newTemplate = {
downloadItem.format = Format( templates.add(it)
it.title, chosenCommandView.editText!!.setText(it.content)
"", downloadItem.format = Format(
"", it.title,
"", "",
"", "",
0, "",
it.content "",
) 0,
preferences.edit().putString("lastCommandTemplateUsed", it.content).apply() it.content
commandTemplateCard.visibility = View.VISIBLE )
view.findViewById<TextView>(R.id.command_txt).visibility = View.VISIBLE preferences.edit().putString("lastCommandTemplateUsed", it.content).apply()
view.findViewById<Chip>(R.id.editSelected).isEnabled = true commandTemplateCard.visibility = View.VISIBLE
populateCommandCard(commandTemplateCard, it) view.findViewById<TextView>(R.id.command_txt).visibility = View.VISIBLE
} view.findViewById<Chip>(R.id.editSelected).isEnabled = true
populateCommandCard(commandTemplateCard, it)
},
dismissed = {}
)
}, },
editSelectedClicked = editSelectedClicked =
{ {
@ -247,21 +251,25 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
chosenCommandView.editText!!.text.toString(), chosenCommandView.editText!!.text.toString(),
useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false
) )
UiUtil.showCommandTemplateCreationOrUpdatingSheet(current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) { UiUtil.showCommandTemplateCreationOrUpdatingSheet(
templates.add(it) current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel,
chosenCommandView.editText!!.setText(it.content) newTemplate = {
populateCommandCard(commandTemplateCard, it) templates.add(it)
downloadItem.format = Format( chosenCommandView.editText!!.setText(it.content)
it.title, populateCommandCard(commandTemplateCard, it)
"", downloadItem.format = Format(
"", it.title,
"", "",
"", "",
0, "",
it.content "",
) 0,
preferences.edit().putString("lastCommandTemplateUsed", it.content).apply() it.content
} )
preferences.edit().putString("lastCommandTemplateUsed", it.content).apply()
},
dismissed = {}
)
}, },
shortcutClicked = { shortcutClicked = {
UiUtil.showShortcuts(requireActivity(), commandTemplateViewModel, UiUtil.showShortcuts(requireActivity(), commandTemplateViewModel,

Some files were not shown because too many files have changed in this diff Show more