├── .gitignore
├── .idea
├── .gitignore
├── .name
├── compiler.xml
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── kotlinc.xml
├── misc.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── json.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── clearpole
│ │ └── videoyou
│ │ └── ExampleInstrumentedTest.kt
│ ├── debug
│ ├── AndroidManifest.xml
│ └── res
│ │ └── values
│ │ └── strings.xml
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── clearpole
│ │ │ └── videoyou
│ │ │ ├── BaseActivity.kt
│ │ │ ├── ErrorCrashActivity.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── PlayListActivity.kt
│ │ │ ├── SearchActivity.kt
│ │ │ ├── SettingActivity.kt
│ │ │ ├── VideoInfoActivity.kt
│ │ │ ├── VideoPlayerActivity.kt
│ │ │ ├── WebDavActivity.kt
│ │ │ ├── adapter
│ │ │ └── MainViewPager.kt
│ │ │ ├── code
│ │ │ ├── MarqueeTextView.java
│ │ │ └── PlayList.kt
│ │ │ ├── model
│ │ │ ├── FolderModel.kt
│ │ │ ├── FolderTreeModel.kt
│ │ │ ├── MainSettingModel.kt
│ │ │ ├── MediaStoreListModel.kt
│ │ │ ├── PlayListModel.kt
│ │ │ ├── PlayListNameModel.kt
│ │ │ ├── PlayerSideSheetModel.kt
│ │ │ ├── SearchModel.kt
│ │ │ ├── SettingThemeModel.kt
│ │ │ ├── VideoInfoModel.kt
│ │ │ ├── VideoUtilsModel.kt
│ │ │ └── WebDavModel.kt
│ │ │ ├── objects
│ │ │ ├── AppObjects.kt
│ │ │ ├── MainObjects.kt
│ │ │ ├── VideoPlayObjects.kt
│ │ │ └── VideoPlayerObjects.kt
│ │ │ ├── ui
│ │ │ └── theme
│ │ │ │ ├── Color.kt
│ │ │ │ └── Theme.kt
│ │ │ └── utils
│ │ │ ├── ByteToString.kt
│ │ │ ├── DatabaseStorage.kt
│ │ │ ├── DeleteVideo.kt
│ │ │ ├── DepthFieldTransformer.kt
│ │ │ ├── GetVideoThumbnail.kt
│ │ │ ├── IsNightMode.kt
│ │ │ ├── NoSwipeViewPager.kt
│ │ │ ├── ReadMediaStore.kt
│ │ │ ├── RefreshMediaStore.kt
│ │ │ ├── SeekBarAnim.kt
│ │ │ ├── SetBarTransparent.kt
│ │ │ ├── SettingsItemsUntil.kt
│ │ │ ├── SubStringX.kt
│ │ │ └── TimeParse.kt
│ └── res
│ │ ├── anim
│ │ ├── alpha_0_1.xml
│ │ └── alpha_1_0.xml
│ │ ├── drawable-v24
│ │ ├── ic_launcher_foreground.xml
│ │ └── ripple.xml
│ │ ├── drawable
│ │ ├── baseline_arrow_back_24.xml
│ │ ├── baseline_arrow_back_small.xml
│ │ ├── baseline_auto_fix_high_24.xml
│ │ ├── baseline_cached_24.xml
│ │ ├── baseline_check_24.xml
│ │ ├── baseline_checklist_rtl_24.xml
│ │ ├── baseline_chevron_right_24.xml
│ │ ├── baseline_code_24.xml
│ │ ├── baseline_delete_forever_24.xml
│ │ ├── baseline_explore_24.xml
│ │ ├── baseline_extension_24.xml
│ │ ├── baseline_folder_open_24.xml
│ │ ├── baseline_format_list_bulleted_24.xml
│ │ ├── baseline_fullscreen_24.xml
│ │ ├── baseline_fullscreen_exit_24.xml
│ │ ├── baseline_gesture_24.xml
│ │ ├── baseline_hearing_24.xml
│ │ ├── baseline_help_24.xml
│ │ ├── baseline_home_24.xml
│ │ ├── baseline_keyboard_arrow_down_24.xml
│ │ ├── baseline_keyboard_arrow_right_24.xml
│ │ ├── baseline_lock_open_24.xml
│ │ ├── baseline_map_24.xml
│ │ ├── baseline_mark_unread_chat_alt_24.xml
│ │ ├── baseline_menu_24.xml
│ │ ├── baseline_note_add_24.xml
│ │ ├── baseline_notifications_none_24.xml
│ │ ├── baseline_pause_24.xml
│ │ ├── baseline_picture_in_picture_24.xml
│ │ ├── baseline_play_arrow_24.xml
│ │ ├── baseline_playlist_add_24.xml
│ │ ├── baseline_playlist_add_check_24.xml
│ │ ├── baseline_refresh_24.xml
│ │ ├── baseline_screen_rotation_24.xml
│ │ ├── baseline_search_24.xml
│ │ ├── baseline_settings_24.xml
│ │ ├── baseline_skip_next_24.xml
│ │ ├── baseline_skip_previous_24.xml
│ │ ├── baseline_web_24.xml
│ │ ├── baseline_webhook_24.xml
│ │ ├── baseline_wifi_tethering_24.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── outline_auto_fix_high_24.xml
│ │ ├── outline_chat_24.xml
│ │ ├── outline_delete_forever_24.xml
│ │ ├── outline_exit_to_app_24.xml
│ │ ├── outline_explore_24.xml
│ │ ├── outline_file_copy_24.xml
│ │ ├── outline_gesture_24.xml
│ │ ├── outline_hearing_disabled_24.xml
│ │ ├── outline_light_mode_24.xml
│ │ ├── outline_lock_24.xml
│ │ ├── outline_mode_night_24.xml
│ │ ├── outline_monetization_on_24.xml
│ │ ├── outline_speed_24.xml
│ │ ├── player_bottom_background.xml
│ │ ├── player_top_background.xml
│ │ ├── twotone_attach_file_24.xml
│ │ ├── twotone_drive_folder_upload_24.xml
│ │ ├── twotone_folder_24.xml
│ │ └── video_player_toolbar_background.xml
│ │ ├── layout
│ │ ├── activity_error_crash.xml
│ │ ├── activity_main.xml
│ │ ├── activity_play_list.xml
│ │ ├── activity_search.xml
│ │ ├── activity_setting.xml
│ │ ├── activity_video_info.xml
│ │ ├── activity_web_dav.xml
│ │ ├── app_is_activation.xml
│ │ ├── compose_videolist.xml
│ │ ├── compose_videoplayer.xml
│ │ ├── compose_videoslider.xml
│ │ ├── folder_list_item.xml
│ │ ├── folder_list_tree_item.xml
│ │ ├── main_drawer_header.xml
│ │ ├── main_page_folder.xml
│ │ ├── main_page_mediastore.xml
│ │ ├── main_page_playlist.xml
│ │ ├── main_page_setting.xml
│ │ ├── main_page_setting_item.xml
│ │ ├── material_dialog_edit_1.xml
│ │ ├── material_dialog_edit_4.xml
│ │ ├── media_store_list_item.xml
│ │ ├── play_list_name_item.xml
│ │ ├── play_list_videos_item.xml
│ │ ├── player_side_sheet.xml
│ │ ├── search_item.xml
│ │ ├── setting_about.xml
│ │ ├── setting_about_do.xml
│ │ ├── setting_currency.xml
│ │ ├── setting_show.xml
│ │ ├── setting_theme.xml
│ │ ├── setting_theme_item.xml
│ │ ├── video_info_item.xml
│ │ ├── video_info_utils_item.xml
│ │ └── webdav_list_item.xml
│ │ ├── menu
│ │ ├── main_choose.xml
│ │ ├── main_drawer.xml
│ │ ├── main_navigation.xml
│ │ ├── main_toolbar.xml
│ │ ├── playlist_toolbar.xml
│ │ ├── video_info.xml
│ │ └── webdav_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ ├── ic_launcher_round.webp
│ │ └── twox.gif
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── values-night
│ │ └── themes.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ └── data_extraction_rules.xml
│ └── test
│ └── java
│ └── com
│ └── clearpole
│ └── videoyou
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | VideoYou - opt
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 项目已迁移至 https://github.com/Clearpole/VideoYouX
2 | # 项目已迁移至 https://github.com/Clearpole/VideoYouX
3 | # 项目已迁移至 https://github.com/Clearpole/VideoYouX
4 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 | apply plugin: 'com.android.application'
6 | android {
7 | namespace 'com.clearpole.videoyou'
8 | compileSdk 33
9 | buildFeatures {
10 | dataBinding true
11 | viewBinding true
12 | compose true
13 | }
14 |
15 | apply plugin: 'kotlin-kapt'
16 |
17 | kapt {
18 | generateStubs = true
19 | }
20 |
21 | defaultConfig {
22 | applicationId "com.clearpole.videoyou"
23 | minSdk 21
24 | targetSdk 33
25 | versionCode 1
26 | if (isCanary()) {
27 | versionName version() + " - " + canary()
28 | } else {
29 | versionName version()
30 | }
31 |
32 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
33 | vectorDrawables {
34 | useSupportLibrary true
35 | }
36 | resConfigs "zh-rCN"
37 | }
38 |
39 | buildTypes {
40 | release {
41 | zipAlignEnabled true
42 | applicationVariants.configureEach { variant ->
43 | variant.outputs.configureEach {
44 | def fileName = "${appName()}-${version()}"
45 | fileName = fileName + "-${releaseTime()}"
46 | if (!isCanary()) {
47 | // 如果是release版本,直接显示
48 | fileName = fileName + "-release.apk"
49 | } else {
50 | fileName = fileName + "-" + canary() + ".apk"
51 | }
52 | outputFileName = fileName
53 | }
54 | }
55 |
56 | }
57 | }
58 | sourceSets {
59 | main {
60 | jniLibs.srcDirs = ['libs']
61 | }
62 | }
63 |
64 | compileOptions {
65 | sourceCompatibility JavaVersion.VERSION_19
66 | targetCompatibility JavaVersion.VERSION_19
67 | }
68 | kotlinOptions {
69 | jvmTarget = '19'
70 | }
71 | composeOptions {
72 | kotlinCompilerExtensionVersion '1.4.0'
73 | }
74 | packagingOptions {
75 | resources {
76 | excludes += '/META-INF/{AL2.0,LGPL2.1}'
77 | }
78 | }
79 | }
80 |
81 | static def version() {
82 | return "0.5.5"
83 | }
84 |
85 | static def isCanary() {
86 | return true
87 | }
88 |
89 | static def appName() {
90 | return "VideoYou"
91 | }
92 |
93 | static def canary() {
94 | return "Beta03"
95 | }
96 |
97 | static def releaseTime() {
98 | return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
99 | }
100 |
101 | dependencies {
102 | implementation 'androidx.core:core-ktx:1.9.0'
103 | implementation 'androidx.appcompat:appcompat:1.6.0'
104 | implementation 'com.google.android.material:material:1.9.0-alpha01'
105 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
106 | implementation 'androidx.compose.compiler:compiler:1.4.0'
107 | implementation 'androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha05'
108 | implementation 'androidx.preference:preference:1.2.0'
109 | api fileTree(include: ['*.jar'], dir: 'libs')
110 | implementation files('libs/json.jar')
111 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
112 | implementation 'androidx.activity:activity-compose:1.5.1'
113 | implementation platform('androidx.compose:compose-bom:2022.10.00')
114 | implementation 'androidx.compose.ui:ui'
115 | implementation 'androidx.compose.ui:ui-graphics'
116 | implementation 'androidx.compose.ui:ui-tooling-preview'
117 | implementation 'androidx.compose.material3:material3:1.1.0-alpha06'
118 | testImplementation 'junit:junit:4.13.2'
119 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
120 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
121 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
122 | //依赖协程核心库
123 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
124 | //依赖当前平台所对应的平台库
125 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
126 |
127 | // ViewBindingKTX:https://github.com/DylanCaiCoding/ViewBindingKTX
128 | implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-ktx:2.1.0'
129 | implementation 'com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-base:2.1.0'
130 | // 状态栏:https://github.com/gyf-dev/ImmersionBar
131 | implementation 'com.geyifeng.immersionbar:immersionbar:3.2.2'
132 | // OkHttp 框架:https://github.com/square/okhttp
133 | implementation 'com.squareup.okhttp3:okhttp:4.10.0'
134 | // 强大的列表组件 https://github.com/liangjingkanji/BRV
135 | implementation 'com.github.liangjingkanji:BRV:1.3.88'
136 | // 权限请求框架:https://github.com/getActivity/XXPermissions
137 | implementation 'com.github.getActivity:XXPermissions:16.6'
138 | // Glide图片加载框架:https://github.com/bumptech/glide
139 | implementation 'com.github.bumptech.glide:glide:4.14.2'
140 | androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
141 | androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
142 | annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
143 | // MMKV —— 基于 mmap 的高性能通用 key-value 组件:https://github.com/Tencent/MMKV/
144 | implementation 'com.tencent:mmkv:1.2.15'
145 | // exoplayer 视频播放框架
146 | implementation 'com.google.android.exoplayer:exoplayer:2.18.2'
147 | // webdav框架:https://github.com/thegrizzlylabs/sardine-android
148 | implementation 'com.thegrizzlylabs.sardine-android:sardine-android:0.8'
149 | // https://github.com/Blankj/AndroidUtilCode/
150 | implementation 'com.blankj:utilcodex:1.31.1'
151 | implementation 'com.github.TutorialsAndroid:crashx:v6.0.19'
152 | debugImplementation 'androidx.compose.ui:ui-tooling'
153 | debugImplementation 'androidx.compose.ui:ui-test-manifest'
154 | }
--------------------------------------------------------------------------------
/app/libs/json.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/libs/json.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | -dontwarn org.bouncycastle.jsse.BCSSLSocket
24 | -dontwarn org.bouncycastle.jsse.BCSSLParameters
25 | -dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
26 | -dontwarn org.conscrypt.*
27 | -dontwarn org.openjsse.javax.net.ssl.SSLParameters
28 | -dontwarn org.openjsse.javax.net.ssl.SSLSocket
29 | -dontwarn org.openjsse.net.ssl.OpenJSSE
30 | -dontwarn com.hjq.permissions.**
31 | #keep 类名和类成员都不会被移除和混淆
32 | -keep class * implements androidx.viewbinding.ViewBinding {
33 | *;
34 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/clearpole/videoyou/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.clearpole.videoyou", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/debug/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
17 |
18 |
19 |
30 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
53 |
56 |
59 |
60 |
61 |
62 |
63 |
66 |
69 |
73 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou
2 |
3 | import android.os.Build
4 | import android.os.Bundle
5 | import androidx.appcompat.app.AppCompatActivity
6 | import androidx.appcompat.app.AppCompatDelegate
7 | import androidx.viewbinding.ViewBinding
8 | import com.clearpole.videoyou.objects.AppObjects
9 | import com.clearpole.videoyou.utils.SettingsItemsUntil
10 | import com.developer.crashx.config.CrashConfig
11 | import com.dylanc.viewbinding.base.ViewBindingUtil
12 | import com.google.android.material.color.DynamicColors
13 | import com.tencent.mmkv.MMKV
14 |
15 |
16 | abstract class BaseActivity : AppCompatActivity() {
17 | lateinit var binding: VB
18 | override fun onCreate(savedInstanceState: Bundle?) {
19 | super.onCreate(savedInstanceState)
20 | MMKV.initialize(this)
21 | val kv = MMKV.mmkvWithID("theme")
22 | val theme = kv.decodeInt("theme")
23 | if (theme.toString().isEmpty()) {
24 | // 第一次进入
25 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
26 | // 安卓版本大于12
27 | kv.encode("theme", 0)
28 | // 动态颜色
29 | DynamicColors.applyToActivityIfAvailable(this)
30 | } else {
31 | // 安卓版本小于12
32 | kv.encode("theme", R.style.hzt)
33 | setTheme(R.style.hzt)
34 | // 默认主题和紫棠
35 | }
36 | } else {
37 | // 不是第一次进入
38 | when (theme) {
39 | 0 -> {
40 | DynamicColors.applyToActivityIfAvailable(this)
41 | AppObjects.theme = 0
42 | }
43 |
44 | R.style.hzt -> {
45 | setTheme(R.style.hzt)
46 | AppObjects.theme = 1
47 | }
48 |
49 | R.style.cxw -> {
50 | setTheme(R.style.cxw)
51 | AppObjects.theme = 2
52 | }
53 |
54 | R.style.szy -> {
55 | setTheme(R.style.szy)
56 | AppObjects.theme = 3
57 | }
58 |
59 | R.style.xfy -> {
60 | setTheme(R.style.xfy)
61 | AppObjects.theme = 4
62 | }
63 | }
64 | }
65 | try {
66 | when (SettingsItemsUntil.readSettingData("darkMode")?.toInt()!!) {
67 | 0 -> {
68 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
69 | }
70 |
71 | 1 -> {
72 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
73 | }
74 |
75 | 2 -> {
76 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
77 | }
78 | }
79 | } catch (_: Exception) {
80 | }
81 | binding = ViewBindingUtil.inflateWithGeneric(this, layoutInflater)
82 | SettingsItemsUntil.fixItems()
83 | setContentView(binding.root)
84 | CrashConfig.Builder.create().errorActivity(ErrorCrashActivity::class.java)
85 | }
86 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/ErrorCrashActivity.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import com.clearpole.videoyou.databinding.ActivityErrorCrashBinding
6 | import com.clearpole.videoyou.utils.IsNightMode
7 | import com.developer.crashx.CrashActivity
8 | import com.gyf.immersionbar.ImmersionBar
9 |
10 | class ErrorCrashActivity : BaseActivity() {
11 | @SuppressLint("RestrictedApi")
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | ImmersionBar.with(this).transparentBar()
15 | .statusBarDarkFont(!IsNightMode.isNightMode(resources)).init()
16 | binding.errorLog.text = CrashActivity.getAllErrorDetailsFromIntent(this,intent)
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/PlayListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou
2 |
3 | import android.media.MediaMetadataRetriever
4 | import android.os.Bundle
5 | import com.blankj.utilcode.util.ToastUtils
6 | import com.clearpole.videoyou.code.PlayList
7 | import com.clearpole.videoyou.databinding.ActivityPlayListBinding
8 | import com.clearpole.videoyou.model.PlayListModel
9 | import com.clearpole.videoyou.utils.IsNightMode
10 | import com.clearpole.videoyou.utils.SubStringX.Companion.subStringX
11 | import com.drake.brv.utils.linear
12 | import com.drake.brv.utils.setup
13 | import com.google.android.material.R.style.MaterialAlertDialog_Material3
14 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
15 | import com.gyf.immersionbar.ImmersionBar
16 | import kotlinx.coroutines.CoroutineScope
17 | import kotlinx.coroutines.Dispatchers
18 | import kotlinx.coroutines.launch
19 | import kotlinx.coroutines.withContext
20 | import org.json.JSONObject
21 |
22 |
23 | class PlayListActivity : BaseActivity() {
24 | override fun onCreate(savedInstanceState: Bundle?) {
25 | super.onCreate(savedInstanceState)
26 | ImmersionBar.with(this).transparentBar()
27 | .statusBarDarkFont(!IsNightMode.isNightMode(resources)).init()
28 | val name = intent.getStringExtra("name")
29 | binding.topAppBar.title = name
30 | CoroutineScope(Dispatchers.IO).launch {
31 | val model = getData()
32 | withContext(Dispatchers.Main) {
33 | binding.listview.linear().setup {
34 | addType { R.layout.media_store_list_item }
35 | }.models = model
36 | }
37 | }
38 | binding.topAppBar.setOnMenuItemClickListener {
39 | when (it.itemId) {
40 | R.id.removePlayList -> {
41 | MaterialAlertDialogBuilder(this, MaterialAlertDialog_Material3)
42 | .setTitle("删除播放列表")
43 | .setMessage("是否删除播放列表《$name》?")
44 | .setNegativeButton("删除") { _, _ ->
45 | PlayList.removeList(name!!)
46 | finish()
47 | ToastUtils.showShort("刷新后生效")
48 | }
49 | .setNeutralButton("取消") { _, _ -> }
50 | .show()
51 | true
52 | }
53 |
54 | else -> false
55 | }
56 | }
57 | }
58 |
59 | private fun getData(): MutableList {
60 | return mutableListOf().apply {
61 | try {
62 | val list =
63 | JSONObject(PlayList.readPlayListContent(intent.getStringExtra("name")!!)!!)
64 | val keys = list.keys()
65 | val retriever = MediaMetadataRetriever()
66 | while (keys.hasNext()) {
67 | val key = keys.next().toString()
68 | val uri = list.getString(key)
69 | retriever.setDataSource(uri)
70 | val title = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf("."))
71 | val duration =
72 | retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
73 | val time = key.subStringX(null, ":")
74 | add(PlayListModel(uri, title, duration, time,list))
75 | }
76 | } catch (_: Exception) {
77 |
78 | }
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/SearchActivity.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou
2 |
3 | import android.annotation.SuppressLint
4 | import android.net.Uri
5 | import android.os.Bundle
6 | import androidx.recyclerview.widget.StaggeredGridLayoutManager
7 | import com.blankj.utilcode.util.ScreenUtils
8 | import com.clearpole.videoyou.databinding.ActivitySearchBinding
9 | import com.clearpole.videoyou.databinding.SearchItemBinding
10 | import com.clearpole.videoyou.model.SearchModel
11 | import com.clearpole.videoyou.utils.DatabaseStorage
12 | import com.clearpole.videoyou.utils.IsNightMode
13 | import com.drake.brv.utils.linear
14 | import com.drake.brv.utils.setup
15 | import com.gyf.immersionbar.ImmersionBar
16 | import kotlinx.coroutines.CoroutineScope
17 | import kotlinx.coroutines.Dispatchers
18 | import kotlinx.coroutines.launch
19 | import org.json.JSONArray
20 | import org.json.JSONObject
21 |
22 |
23 | class SearchActivity : BaseActivity() {
24 | override fun onCreate(savedInstanceState: Bundle?) {
25 | super.onCreate(savedInstanceState)
26 | ImmersionBar.with(this).transparentBar()
27 | .statusBarDarkFont(!IsNightMode.isNightMode(resources)).init()
28 | binding.catSearchView.editText.setOnEditorActionListener { v, _, _ ->
29 | binding.catSearchBar.text = v.text
30 | setSearchList(v.text.toString())
31 | binding.catSearchView.hide()
32 | false
33 | }
34 | binding.searchRv.layoutParams.height = ScreenUtils.getAppScreenHeight()
35 | }
36 |
37 | @SuppressLint("CutPasteId", "SetTextI18n")
38 | private fun setSearchList(key: String) {
39 | CoroutineScope(Dispatchers.IO).launch {
40 | val models = getDataForSearch(key, DatabaseStorage.readDataByData()!!)
41 | launch(Dispatchers.Main) {
42 | binding.searchRv.linear().setup {
43 | addType { R.layout.search_item }
44 | onCreate {
45 | val binding = SearchItemBinding.bind(itemView)
46 | binding.itemImg.layoutParams.height = (160..300).random()
47 | }
48 | }.models = models
49 | binding.searchRv.layoutManager = StaggeredGridLayoutManager(
50 | 2,
51 | StaggeredGridLayoutManager.VERTICAL
52 | )
53 | }
54 | }
55 | }
56 |
57 | private fun getDataForSearch(key: String, kv: JSONArray): MutableList {
58 | return mutableListOf().apply {
59 | for (index in 0 until kv.length()) {
60 | val jsonObject = JSONObject(kv.getString(index))
61 | if (jsonObject.getString("title").contains(key)) {
62 | add(
63 | SearchModel(
64 | title = jsonObject.getString("title"),
65 | size = jsonObject.getString("size"),
66 | uri = Uri.parse(jsonObject.getString("uri")),
67 | path = jsonObject.getString("path"),
68 | )
69 | )
70 | }
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/adapter/MainViewPager.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.adapter
2 |
3 | import android.view.View
4 | import android.view.ViewGroup
5 | import androidx.viewpager.widget.PagerAdapter
6 |
7 | class MainViewPager : PagerAdapter {
8 | // 定义视图列表
9 | private var viewList: List = ArrayList()
10 |
11 | // 构造方法传入数据
12 | constructor(viewList: List) {
13 | this.viewList = viewList
14 | }
15 |
16 | constructor()
17 |
18 | //初始化指定位置的页面
19 | override fun instantiateItem(container: ViewGroup, position: Int): Any {
20 |
21 | //将页面加入容器
22 | container.addView(viewList[position])
23 | //返回加载的页面
24 | return viewList[position]
25 | }
26 |
27 | //销毁指定位置的页面
28 | override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
29 | container.removeView(viewList[position]) //删除页面
30 | }
31 |
32 | //显示多少个页面
33 | override fun getCount(): Int {
34 | return viewList.size
35 | }
36 |
37 | //判断view 是否是object
38 | override fun isViewFromObject(view: View, `object`: Any): Boolean {
39 | return view === `object`
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/code/MarqueeTextView.java:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.code;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.util.AttributeSet;
6 |
7 | import androidx.annotation.Nullable;
8 |
9 | import com.google.android.material.textview.MaterialTextView;
10 |
11 | @SuppressLint("AppCompatCustomView")
12 | public class MarqueeTextView extends MaterialTextView {
13 |
14 | public MarqueeTextView(Context context) {
15 | super(context);
16 | }
17 |
18 | public MarqueeTextView(Context context, @Nullable AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public MarqueeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
23 | super(context, attrs, defStyleAttr);
24 | }
25 |
26 | public MarqueeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
27 | super(context, attrs, defStyleAttr, defStyleRes);
28 | }
29 |
30 | @Override
31 | public boolean isFocused() {
32 | return true;
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/code/PlayList.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.code
2 |
3 | import android.annotation.SuppressLint
4 | import com.blankj.utilcode.util.TimeUtils
5 | import com.tencent.mmkv.MMKV
6 | import kotlinx.coroutines.CoroutineScope
7 | import kotlinx.coroutines.Dispatchers
8 | import kotlinx.coroutines.launch
9 | import kotlinx.coroutines.withContext
10 | import org.json.JSONObject
11 |
12 | class PlayList {
13 | companion object {
14 | private val mainKv = MMKV.mmkvWithID("videoyou-playlist-name")
15 | private val nextKv = MMKV.mmkvWithID("videoyou-playlist-content")
16 |
17 | // 用于存放视频列表的名称,仅存放名称
18 | fun addList(name: String) {
19 | val json = JSONObject()
20 | json.put(
21 | "time", TimeUtils.getNowMills()
22 | )
23 | json.put("index", mainKv.count() + 1)
24 | json.put("count", 0)
25 | mainKv.putString(name, json.toString())
26 | // 将名称存入储存库,赋值的是它的索引
27 | }
28 |
29 | @SuppressLint("SimpleDateFormat")
30 | fun readList(): List {
31 | return mainKv.allKeys()!!.sortedBy {
32 | TimeUtils.millis2Date(
33 | JSONObject(
34 | mainKv.decodeString(it).toString()
35 | ).getLong("time")
36 | )
37 | }.reversed()
38 | // 返回名称存储库内所有的名称
39 | }
40 |
41 | fun readListContent(name: String): String? {
42 | return mainKv.decodeString(name)
43 | }
44 |
45 | fun removeList(name: String) {
46 | mainKv.remove(name)
47 | nextKv.remove(name)
48 | }
49 |
50 | fun addPlayListContent(name: String, list: ArrayList) {
51 | if (!nextKv.decodeString(name).isNullOrEmpty()) {
52 | CoroutineScope(Dispatchers.IO).launch {
53 | val late = JSONObject(nextKv.decodeString(name)!!)
54 | val keys = JSONObject(nextKv.decodeString(name)!!).keys()
55 | while (keys.hasNext()) {
56 | val time = keys.next().toString()
57 | val uri = late.getString(time)
58 | if (list.contains(uri)) {
59 | late.remove(time)
60 | }
61 | }
62 | withContext(Dispatchers.IO) {
63 | list.forEachIndexed { _, s ->
64 | late.put(
65 | TimeUtils.getNowMills().toString() + ":${(0..9999999).random()}", s
66 | )
67 | nextKv.encode(name, late.toString())
68 | }
69 | }
70 | }
71 | } else {
72 | val json = JSONObject()
73 | list.forEachIndexed { _, s ->
74 | json.put(TimeUtils.getNowMills().toString() + ":${(0..9999999).random()}", s)
75 | nextKv.encode(name, json.toString())
76 | }
77 | }
78 | }
79 |
80 | fun readPlayListContent(name: String): String? {
81 | return nextKv.decodeString(name)
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/FolderModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.content.ContentResolver
4 | import android.net.Uri
5 | import android.view.View
6 | import androidx.databinding.BaseObservable
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
9 | import com.clearpole.videoyou.databinding.FolderListItemBinding
10 | import com.clearpole.videoyou.utils.GetVideoThumbnail
11 | import com.drake.brv.BindingAdapter
12 | import com.drake.brv.item.ItemBind
13 | import com.drake.brv.item.ItemExpand
14 | import kotlinx.coroutines.CoroutineScope
15 | import kotlinx.coroutines.Dispatchers
16 | import kotlinx.coroutines.cancel
17 | import kotlinx.coroutines.launch
18 | import kotlinx.coroutines.withContext
19 |
20 |
21 | open class FolderModel(
22 | override var itemGroupPosition: Int = 0,
23 | override var itemExpand: Boolean = false,
24 | override var itemSublist: List? = null,
25 | var checked: Boolean = false,
26 | var vis: Int = View.GONE,
27 | val title: String,
28 | val uri: Uri,
29 | val path: String
30 | ) : ItemExpand, ItemBind, BaseObservable() {
31 | val videoTitle get() = title
32 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
33 |
34 | val binding = holder.getBinding()
35 | CoroutineScope(Dispatchers.IO).launch {
36 | withContext(Dispatchers.Main) {
37 | Glide.with(holder.context)
38 | .load(uri)
39 | .transition(DrawableTransitionOptions.withCrossFade())
40 | .into(binding.page2RvItemImg)
41 | }
42 | this.cancel()
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/FolderTreeModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.ContentResolver
5 | import android.graphics.drawable.Drawable
6 | import android.net.Uri
7 | import androidx.databinding.BaseObservable
8 | import com.clearpole.videoyou.objects.MainObjects
9 | import com.drake.brv.item.ItemExpand
10 | import com.drake.brv.item.ItemHover
11 | import com.drake.brv.item.ItemPosition
12 | import org.json.JSONArray
13 | import org.json.JSONObject
14 |
15 | open class FolderTreeModel(
16 | private val contentResolver: ContentResolver,
17 | val path: String?,
18 | private val json: JSONArray,
19 | private val openImg: Drawable,
20 | private val closeImg: Drawable
21 | ) : ItemExpand, ItemHover, ItemPosition,
22 | BaseObservable() {
23 |
24 | override var itemGroupPosition: Int = 0
25 | override var itemExpand: Boolean = false
26 | set(value) {
27 | field = value
28 | notifyChange()
29 | }
30 |
31 | override var itemSublist: List?
32 | get() = jsonSublist
33 | set(value) {
34 | @Suppress("UNCHECKED_CAST")
35 | jsonSublist = value as List
36 | }
37 | private var jCount = 0
38 | private var jsonSublist: List = mutableListOf().apply {
39 | for (index in 0 until json.length()) {
40 | val objects = JSONObject(json.getString(index))
41 | var folder = "根目录"
42 | try {
43 | folder = objects.getString("folder")
44 | } catch (_: Exception) {
45 | }
46 | if (folder == title) {
47 | add(
48 | FolderModel(
49 | title = objects.getString("title"),
50 | uri = Uri.parse(objects.getString("uri")),
51 | path = objects.getString("path")
52 | )
53 | )
54 | jCount += 1
55 | MainObjects.count = jCount
56 | }
57 | }
58 | }
59 |
60 | override var itemHover: Boolean = true
61 | override var itemPosition: Int = 0
62 |
63 |
64 | val title get() = path
65 | val expandIcon
66 | @SuppressLint("ResourceType")
67 | get() = if (itemExpand) openImg else closeImg
68 | val count get() = jCount
69 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/MainSettingModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.content.Intent
4 | import android.graphics.drawable.Drawable
5 | import com.bumptech.glide.Glide
6 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
7 | import com.clearpole.videoyou.SettingActivity
8 | import com.clearpole.videoyou.databinding.MainPageSettingItemBinding
9 | import com.drake.brv.BindingAdapter
10 | import com.drake.brv.item.ItemBind
11 |
12 | data class MainSettingModel(val title: String, val info: String, val img: Drawable) : ItemBind {
13 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
14 | val binding = holder.getBinding()
15 | binding.title.text = title
16 | binding.info.text = info
17 | Glide.with(holder.context).load(img).transition(DrawableTransitionOptions.withCrossFade())
18 | .into(binding.sLI)
19 | binding.root.setOnClickListener {
20 | val intent = Intent(holder.context,SettingActivity::class.java)
21 | intent.putExtra("name",title)
22 | holder.context.startActivity(intent)
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/MediaStoreListModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import android.view.View
8 | import androidx.core.app.ActivityOptionsCompat
9 | import com.blankj.utilcode.util.ActivityUtils.startActivity
10 | import com.bumptech.glide.Glide
11 | import com.bumptech.glide.load.engine.DiskCacheStrategy
12 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
13 | import com.clearpole.videoyou.VideoInfoActivity
14 | import com.clearpole.videoyou.VideoPlayerActivity
15 | import com.clearpole.videoyou.databinding.ActivityMainBinding
16 | import com.clearpole.videoyou.databinding.MediaStoreListItemBinding
17 | import com.clearpole.videoyou.objects.VideoPlayObjects
18 | import com.clearpole.videoyou.utils.GetVideoThumbnail
19 | import com.drake.brv.BindingAdapter
20 | import com.drake.brv.item.ItemBind
21 | import kotlinx.coroutines.CoroutineScope
22 | import kotlinx.coroutines.Dispatchers
23 | import kotlinx.coroutines.cancel
24 | import kotlinx.coroutines.launch
25 | import kotlinx.coroutines.withContext
26 |
27 |
28 | data class MediaStoreListModel(
29 | val title: String,
30 | val size: String,
31 | val uri: Uri,
32 | val path: String,
33 | val mainBind: ActivityMainBinding?,
34 | val activity: Activity
35 | ) : ItemBind {
36 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
37 | val binding = MediaStoreListItemBinding.bind(holder.itemView)
38 | binding.itemName.text = title
39 | binding.itemSize.text = size
40 | binding.itemRoot.setOnClickListener {
41 | VideoPlayObjects.paths = path
42 | VideoPlayObjects.title = title
43 | VideoPlayObjects.type = "LOCAL"
44 | VideoPlayObjects.list = mutableListOf(path)
45 | VideoPlayObjects.uri = uri
46 | val intent = Intent(holder.context, VideoInfoActivity::class.java)
47 | val bundle: Bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
48 | activity,
49 | binding.card,
50 | "VideoYouInfoImageName"
51 | ).toBundle()!!
52 | intent.data = uri
53 | intent.putExtra("int","0")
54 | startActivity(intent, bundle)
55 | }
56 |
57 | CoroutineScope(Dispatchers.IO).launch {
58 | withContext(Dispatchers.Main) {
59 | Glide.with(holder.context).load(uri)
60 | .transition(DrawableTransitionOptions.withCrossFade()).into(binding.itemCover)
61 | }
62 | this.cancel()
63 | }
64 |
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/PlayListModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.content.Intent
4 | import com.blankj.utilcode.util.ActivityUtils
5 | import com.bumptech.glide.Glide
6 | import com.bumptech.glide.load.engine.DiskCacheStrategy
7 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
8 | import com.clearpole.videoyou.VideoPlayerActivity
9 | import com.clearpole.videoyou.databinding.MediaStoreListItemBinding
10 | import com.clearpole.videoyou.objects.VideoPlayObjects
11 | import com.clearpole.videoyou.objects.VideoPlayerObjects
12 | import com.clearpole.videoyou.utils.TimeParse
13 | import com.drake.brv.BindingAdapter
14 | import com.drake.brv.item.ItemBind
15 | import kotlinx.coroutines.CoroutineScope
16 | import kotlinx.coroutines.Dispatchers
17 | import kotlinx.coroutines.launch
18 | import kotlinx.coroutines.withContext
19 | import org.json.JSONObject
20 |
21 | data class PlayListModel(
22 | val uri: String,
23 | val title: String?,
24 | val duration: String?,
25 | val time: String?,
26 | val list: JSONObject
27 | ) : ItemBind {
28 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
29 | val binding = MediaStoreListItemBinding.bind(holder.itemView)
30 | binding.itemName.text = title
31 | Glide.with(holder.context).load(uri).diskCacheStrategy(DiskCacheStrategy.RESOURCE)
32 | .transition(
33 | DrawableTransitionOptions.withCrossFade()
34 | ).into(binding.itemCover)
35 | binding.itemSize.text = TimeParse.timeParse(duration!!.toLong())
36 | binding.itemRoot.setOnClickListener {
37 | CoroutineScope(Dispatchers.IO).launch {
38 | val array = arrayListOf()
39 | val keys = list.keys()
40 | while (keys.hasNext()) {
41 | val key = keys.next().toString()
42 | val uri = list.getString(key)
43 | array.add(uri)
44 | VideoPlayObjects.list = array.toMutableList()
45 | }
46 | VideoPlayObjects.title = title.toString()
47 | VideoPlayObjects.type = "LOCAL"
48 | VideoPlayerObjects.newItem = holder.layoutPosition
49 | withContext(Dispatchers.Main) {
50 | val intent = Intent(holder.context, VideoPlayerActivity::class.java)
51 | ActivityUtils.startActivity(intent)
52 | }
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/PlayListNameModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.content.Intent
4 | import com.bumptech.glide.Glide
5 | import com.bumptech.glide.load.engine.DiskCacheStrategy
6 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
7 | import com.clearpole.videoyou.PlayListActivity
8 | import com.clearpole.videoyou.code.PlayList
9 | import com.clearpole.videoyou.databinding.PlayListNameItemBinding
10 | import com.clearpole.videoyou.utils.SubStringX.Companion.subStringX
11 | import com.drake.brv.BindingAdapter
12 | import com.drake.brv.item.ItemBind
13 | import org.json.JSONObject
14 |
15 | data class PlayListNameModel(val title: String, val time: String, val count: String) : ItemBind {
16 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
17 | val binding = PlayListNameItemBinding.bind(holder.itemView)
18 | try {
19 | val list = JSONObject(PlayList.readPlayListContent(title)!!)
20 | val key = list.toString().subStringX("\"", "\"")
21 | val uri = list.getString(key!!)
22 |
23 | binding.playListFilesTitle.text = title
24 | binding.webDavFilesPath.text = buildString {
25 | append(time)
26 | append(" · ")
27 | append(list.length())
28 | }
29 | Glide.with(holder.context).load(uri).diskCacheStrategy(DiskCacheStrategy.RESOURCE)
30 | .transition(
31 | DrawableTransitionOptions.withCrossFade()
32 | ).into(binding.cover)
33 | binding.playListFilesRoot.setOnClickListener {
34 | val int = Intent(holder.context, PlayListActivity::class.java)
35 | int.putExtra("name", title)
36 | holder.context.startActivity(int)
37 | }
38 | }catch (e:Exception){
39 | binding.playListFilesTitle.text = title
40 | binding.webDavFilesPath.text = buildString {
41 | append(time)
42 | append(" · ")
43 | append(0)
44 | }
45 | binding.playListFilesRoot.setOnClickListener {
46 | val int = Intent(holder.context, PlayListActivity::class.java)
47 | int.putExtra("name", title)
48 | holder.context.startActivity(int)
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/PlayerSideSheetModel.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("DEPRECATION")
2 |
3 | package com.clearpole.videoyou.model
4 |
5 | import android.annotation.SuppressLint
6 | import android.content.res.Resources
7 | import com.blankj.utilcode.util.ToastUtils
8 | import com.clearpole.videoyou.R
9 | import com.clearpole.videoyou.databinding.PlayListVideosItemBinding
10 | import com.clearpole.videoyou.objects.AppObjects
11 | import com.clearpole.videoyou.objects.VideoPlayObjects
12 | import com.clearpole.videoyou.objects.VideoPlayerObjects
13 | import com.drake.brv.BindingAdapter
14 | import com.drake.brv.item.ItemBind
15 | import com.drake.brv.utils.bindingAdapter
16 | import com.drake.brv.utils.mutable
17 |
18 | data class PlayerSideSheetModel(
19 | val path: String,
20 | val resources: Resources,
21 | val item:Int
22 | ) : ItemBind {
23 | @SuppressLint("ResourceAsColor", "UseCompatLoadingForDrawables")
24 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
25 | val binding = PlayListVideosItemBinding.bind(holder.itemView)
26 | val chose = when (AppObjects.theme) {
27 | 0 -> {
28 | resources.getColor(R.color.color3)
29 | }
30 |
31 | 1 -> {
32 | resources.getColor(R.color.hzt_theme_dark_primary)
33 | }
34 |
35 | 2 -> {
36 | resources.getColor(R.color.cxw_theme_dark_primary)
37 | }
38 |
39 | 3 -> {
40 | resources.getColor(R.color.szy_theme_dark_primary)
41 | }
42 |
43 | 4 -> {
44 | resources.getColor(R.color.xfy_theme_dark_primary)
45 | }
46 |
47 | else -> {
48 | resources.getColor(R.color.chose)
49 | }
50 | }
51 | if (item==holder.layoutPosition){
52 | binding.title.setTextColor(chose)
53 | VideoPlayerObjects.chose = binding.title
54 | }else{
55 | binding.title.setTextColor(android.graphics.Color.parseColor("#ffffff"))
56 | }
57 | binding.title.text = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."))
58 | binding.title.maxLines = 3
59 | binding.title.textSize = 14f
60 | binding.root.setOnClickListener {
61 | if (item!=holder.layoutPosition) {
62 | VideoPlayerObjects.player.seekToDefaultPosition(holder.layoutPosition)
63 | VideoPlayerObjects.chose = binding.title
64 | }
65 | }
66 | binding.close.setOnClickListener {
67 | try {
68 | VideoPlayerObjects.player.removeMediaItem(holder.layoutPosition)
69 | VideoPlayerObjects.rv!!.mutable.removeAt(holder.layoutPosition)
70 | VideoPlayerObjects.rv!!.bindingAdapter.notifyItemRemoved(holder.layoutPosition)
71 | VideoPlayObjects.list.removeAt(holder.layoutPosition)
72 | if (VideoPlayerObjects.player.mediaItemCount==0){
73 | ToastUtils.showLong("无播放项目")
74 | }
75 | }catch (_:Exception){
76 | ToastUtils.showShort("删除失败,请重试")
77 | }
78 | false
79 | }
80 |
81 | }
82 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/SearchModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.content.Intent
4 | import android.net.Uri
5 | import com.blankj.utilcode.util.ActivityUtils
6 | import com.bumptech.glide.Glide
7 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
8 | import com.clearpole.videoyou.VideoPlayerActivity
9 | import com.clearpole.videoyou.databinding.SearchItemBinding
10 | import com.clearpole.videoyou.objects.VideoPlayObjects
11 | import com.clearpole.videoyou.utils.GetVideoThumbnail
12 | import com.drake.brv.BindingAdapter
13 | import com.drake.brv.item.ItemBind
14 | import kotlinx.coroutines.CoroutineScope
15 | import kotlinx.coroutines.Dispatchers
16 | import kotlinx.coroutines.cancel
17 | import kotlinx.coroutines.launch
18 | import kotlinx.coroutines.withContext
19 |
20 | data class SearchModel(
21 | val title: String,
22 | val size: String,
23 | val uri: Uri,
24 | val path: String
25 | ) :
26 | ItemBind {
27 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
28 | val binding = holder.getBinding()
29 | binding.itemText.text = title
30 | binding.itemRoot.setOnClickListener {
31 | VideoPlayObjects.paths = path
32 | VideoPlayObjects.title = title
33 | VideoPlayObjects.type = "LOCAL"
34 | VideoPlayObjects.list = mutableListOf(path)
35 | val intent = Intent(holder.context, VideoPlayerActivity::class.java)
36 | ActivityUtils.startActivity(intent)
37 | }
38 | CoroutineScope(Dispatchers.IO).launch {
39 | val bitmap =
40 | GetVideoThumbnail.getVideoThumbnail(holder.context.contentResolver, uri)
41 | withContext(Dispatchers.Main) {
42 | Glide.with(holder.context)
43 | .load(bitmap)
44 | .transition(DrawableTransitionOptions.withCrossFade())
45 | .into(binding.itemImg)
46 | }
47 | this.cancel()
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/SettingThemeModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.annotation.SuppressLint
4 | import com.blankj.utilcode.util.AppUtils
5 | import com.clearpole.videoyou.R
6 | import com.clearpole.videoyou.databinding.SettingThemeItemBinding
7 | import com.drake.brv.BindingAdapter
8 | import com.drake.brv.item.ItemBind
9 | import com.google.android.material.R.style.MaterialAlertDialog_Material3
10 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
11 | import com.tencent.mmkv.MMKV
12 |
13 | data class SettingThemeModel(val name: String, val type: Int) : ItemBind {
14 | @SuppressLint("ResourceAsColor", "UseCompatLoadingForDrawables")
15 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
16 | val binding = holder.getBinding()
17 | binding.name.text = name
18 | val theme = MMKV.mmkvWithID("theme").decodeInt("theme")
19 | if (type == theme) {
20 | binding.cardView.isChecked = true
21 | }
22 | when (type) {
23 | 0 -> {
24 | binding.mainBack.background = holder.context.getDrawable(R.color.color1)
25 | binding.floating.background = holder.context.getDrawable(R.color.color4)
26 | }
27 |
28 | R.style.hzt -> {
29 | binding.mainBack.background = holder.context.getDrawable(R.color.hzt_theme_dark_primary)
30 | binding.floating.background = holder.context.getDrawable(R.color.hzt_theme_light_primary)
31 | }
32 |
33 | R.style.cxw -> {
34 | binding.mainBack.background = holder.context.getDrawable(R.color.cxw_theme_dark_primary)
35 | binding.floating.background = holder.context.getDrawable(R.color.cxw_theme_light_primary)
36 | }
37 |
38 | R.style.szy -> {
39 | binding.mainBack.background = holder.context.getDrawable(R.color.szy_theme_dark_primary)
40 | binding.floating.background = holder.context.getDrawable(R.color.szy_theme_light_primary)
41 | }
42 |
43 | R.style.xfy -> {
44 | binding.mainBack.background = holder.context.getDrawable(R.color.xfy_theme_dark_primary)
45 | binding.floating.background = holder.context.getDrawable(R.color.xfy_theme_light_primary)
46 | }
47 | }
48 | binding.cardView.setOnClickListener {
49 | if (theme != type) {
50 | MMKV.mmkvWithID("theme").encode("theme", type)
51 | MaterialAlertDialogBuilder(holder.context, MaterialAlertDialog_Material3)
52 | .setTitle(name)
53 | .setMessage("您已选择主题:$name,重启即可生效。")
54 | .setNegativeButton("重启") { _, _ ->
55 | AppUtils.relaunchApp()
56 | }
57 | .setCancelable(false)
58 | .show()
59 | }
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/VideoInfoModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import com.blankj.utilcode.util.ClipboardUtils
4 | import com.clearpole.videoyou.databinding.VideoInfoItemBinding
5 | import com.drake.brv.BindingAdapter
6 | import com.drake.brv.item.ItemBind
7 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
8 |
9 | data class VideoInfoModel(val title: String, val info: String) : ItemBind {
10 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
11 | val binding = holder.getBinding()
12 | binding.name.text = title
13 | binding.info.text = info
14 | binding.root.setOnClickListener {
15 | MaterialAlertDialogBuilder(holder.context).setTitle(
16 | title
17 | ).setMessage(info).setPositiveButton("复制") { _, _ ->
18 | ClipboardUtils.copyText(info)
19 | }.show()
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/VideoUtilsModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model
2 |
3 | import android.graphics.drawable.Drawable
4 | import com.bumptech.glide.Glide
5 | import com.clearpole.videoyou.databinding.VideoInfoUtilsItemBinding
6 | import com.drake.brv.BindingAdapter
7 | import com.drake.brv.item.ItemBind
8 |
9 | data class VideoUtilsModel(val icon:Drawable,val name:String, val util:()->Unit):ItemBind {
10 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
11 | val binding = holder.getBinding()
12 | Glide.with(holder.context).load(icon).into(binding.icon)
13 | binding.name.text = name
14 | binding.root.setOnClickListener {
15 | util()
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/model/WebDavModel.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.model;
2 |
3 | import com.drake.brv.BindingAdapter
4 | import com.drake.brv.item.ItemBind
5 | import com.thegrizzlylabs.sardineandroid.DavResource
6 |
7 | data class WebDavModel(
8 | val title: DavResource
9 | ) :
10 | ItemBind {
11 | override fun onBind(holder: BindingAdapter.BindingViewHolder) {
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/objects/AppObjects.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.objects
2 |
3 | class AppObjects {
4 | companion object{
5 | var theme = 0
6 | }
7 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/objects/MainObjects.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.objects
2 |
3 | import android.net.Uri
4 | import android.view.View
5 | import org.json.JSONObject
6 |
7 | class MainObjects {
8 | companion object{
9 | var allSize : Long = 0
10 | var isChoose = false
11 | val chooseList = ArrayList()
12 | var count : Int = 0
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/objects/VideoPlayObjects.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.objects
2 |
3 | import android.graphics.Bitmap
4 | import android.net.Uri
5 | import com.thegrizzlylabs.sardineandroid.DavResource
6 | import org.json.JSONObject
7 |
8 | class VideoPlayObjects {
9 | companion object {
10 | lateinit var type: String
11 | lateinit var paths: String
12 | lateinit var title: String
13 | lateinit var cover: Bitmap
14 | lateinit var uri: Uri
15 | var list = mutableListOf()
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/objects/VideoPlayerObjects.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.objects
2 |
3 | import android.annotation.SuppressLint
4 | import android.widget.TextView
5 | import androidx.constraintlayout.widget.ConstraintLayout
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.google.android.exoplayer2.ExoPlayer
8 | import com.google.android.material.slider.Slider
9 |
10 | class VideoPlayerObjects {
11 | companion object{
12 | var videoWidth : Int = 0
13 | var videoHeight : Int = 0
14 | var isAutoFinish : Boolean = false
15 | var newItem : Int = 0
16 | var isSpeedMode : Boolean = false
17 | var isPauseMode : Boolean = false
18 | var isToolBarOpen : Boolean = false
19 | var isInFullScreen : Boolean = false
20 | var isIntoHome : Boolean = false
21 | var isCrash : Boolean = false
22 | var isMove : Boolean = false
23 | var fingerX : Long = 0L
24 | var slider : Slider? = null
25 | var pausing : Boolean = false
26 | var first : Boolean = true
27 | var speed : Float = 2f
28 | var playMode : Int = ExoPlayer.REPEAT_MODE_ALL
29 | @SuppressLint("StaticFieldLeak")
30 | var chose : TextView? = null
31 | var rv: RecyclerView? = null
32 | lateinit var player: ExoPlayer
33 | fun fix(){
34 | videoWidth = 0
35 | videoHeight = 0
36 | isAutoFinish = false
37 | newItem = 0
38 | isSpeedMode = false
39 | isPauseMode = false
40 | isToolBarOpen = false
41 | isInFullScreen = false
42 | isIntoHome = false
43 | fingerX = 0L
44 | isCrash = true
45 | isMove = false
46 | slider = null
47 | first = true
48 | pausing = false
49 | chose = null
50 | rv = null
51 | speed = 2f
52 | playMode = ExoPlayer.REPEAT_MODE_ALL
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/ByteToString.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import java.text.DecimalFormat
4 |
5 | class ByteToString {
6 | companion object {
7 | fun byteToString(size: Long): String {
8 | val gB = (1024 * 1024 * 1024).toLong()
9 | val mB = (1024 * 1024).toLong()
10 | val kB: Long = 1024
11 | val df = DecimalFormat("0.00")
12 | val resultSize: String = if (size / gB >= 1) {
13 | df.format(size / gB.toFloat()) + " GB "
14 | } else if (size / mB >= 1) {
15 | df.format(size / mB.toFloat()) + " MB "
16 | } else if (size / kB >= 1) {
17 | df.format(size / kB.toFloat()) + " KB "
18 | } else {
19 | "$size B "
20 | }
21 | return resultSize
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/DatabaseStorage.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.content.ContentResolver
4 | import com.tencent.mmkv.MMKV
5 | import kotlinx.coroutines.CoroutineScope
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.launch
8 | import org.json.JSONArray
9 |
10 | class DatabaseStorage {
11 | companion object {
12 | private val kv = MMKV.mmkvWithID("MediaStore")
13 | fun writeDataToData(list: JSONArray): Boolean {
14 | var isSuccess = false
15 | CoroutineScope(Dispatchers.IO).launch {
16 | for (index in 0 until list.length()) {
17 | isSuccess = kv.encode(index.toString(), list[index].toString())
18 | }
19 | }
20 | return isSuccess
21 | }
22 |
23 | fun readDataByData(): JSONArray? = try {
24 | val kV = kv.allKeys()
25 | val array = JSONArray()
26 | for (index in kV!!.indices) {
27 | val jsonObject = kv.decodeString(kV[index])
28 | array.put(jsonObject)
29 | }
30 | array
31 | } catch (e: Exception) {
32 | null
33 | }
34 |
35 | fun clearData(contentResolver: ContentResolver) {
36 | kv.clear()
37 | writeDataToData(ReadMediaStore.start(contentResolver))
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/DeleteVideo.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.content.Context
4 | import android.provider.MediaStore
5 | import com.blankj.utilcode.util.ToastUtils
6 | import java.io.File
7 |
8 |
9 | public fun deleteVideo(file: File,context: Context) {
10 | if (file.isFile) {
11 | val filePath = file.path
12 | val res: Int = context.contentResolver.delete(
13 | MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
14 | MediaStore.Audio.Media.DATA + "= \"" + filePath + "\"",
15 | null
16 | )
17 | if (res > 0) {
18 | file.delete()
19 | } else {
20 | ToastUtils.showShort("删除失败")
21 | }
22 | return
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/DepthFieldTransformer.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.view.View
4 | import androidx.viewpager.widget.ViewPager
5 | import androidx.viewpager2.widget.ViewPager2
6 | import kotlin.math.abs
7 |
8 | private const val MIN_SCALE = 0.8f
9 |
10 | class DepthFieldTransformer : ViewPager2.PageTransformer, ViewPager.PageTransformer {
11 | override fun transformPage(page: View, position: Float) {
12 | page.apply {
13 | when {
14 | position < -1 -> {
15 | alpha = 1f - MIN_SCALE
16 | scaleX = MIN_SCALE
17 | scaleY = MIN_SCALE
18 | }
19 | position <= 1 -> {
20 | val absPos = abs(position)
21 | val scale = if (absPos > 1) 0F else 1 - absPos
22 | page.scaleX = MIN_SCALE + (1f - MIN_SCALE) * scale
23 | page.scaleY = MIN_SCALE + (1f - MIN_SCALE) * scale
24 | page.alpha = MIN_SCALE + (1f - MIN_SCALE) * scale
25 | }
26 | else -> {
27 | page.scaleX = 0f
28 | page.scaleY = 0f
29 | page.alpha = 0f
30 | }
31 | }
32 | }
33 |
34 |
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/GetVideoThumbnail.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.ContentResolver
5 | import android.graphics.Bitmap
6 | import android.graphics.BitmapFactory
7 | import android.net.Uri
8 | import android.provider.MediaStore
9 |
10 |
11 | class GetVideoThumbnail {
12 | companion object {
13 | @Suppress("DEPRECATION", "UNUSED_EXPRESSION")
14 | @SuppressLint("Range")
15 | fun getVideoThumbnail(cr: ContentResolver, uri: Uri?): Bitmap? {
16 | return try {
17 | var bitmap: Bitmap?
18 | val options = BitmapFactory.Options()
19 | options.inDither = false
20 | options.inPreferredConfig = Bitmap.Config.RGB_565
21 | val cursor = cr.query(uri!!, arrayOf(MediaStore.Video.Media._ID), null, null, null)
22 | if (cursor == null || cursor.count == 0) {
23 | null
24 | }
25 | cursor!!.moveToFirst()
26 | val videoId = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media._ID))
27 | ?: null //image id in image table.s
28 | cursor.close()
29 | val videoIdLong = videoId!!.toLong()
30 | bitmap = MediaStore.Video.Thumbnails.getThumbnail(
31 | cr, videoIdLong, MediaStore.Images.Thumbnails.MINI_KIND, options
32 | )
33 | bitmap
34 | } catch (e: Exception) {
35 | null
36 | }
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/IsNightMode.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.content.res.Configuration
4 | import android.content.res.Resources
5 |
6 | class IsNightMode {
7 | companion object{
8 | fun isNightMode(resources: Resources): Boolean {
9 | return when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
10 | Configuration.UI_MODE_NIGHT_YES -> true
11 | else -> false
12 | }
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/NoSwipeViewPager.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.MotionEvent
6 | import androidx.viewpager.widget.ViewPager
7 |
8 |
9 | //禁止滑动的viewpager
10 | class NoSwipeViewPager(context: Context?, attributeSet: AttributeSet?) :
11 | ViewPager(context!!, attributeSet) {
12 | private var canSwipe = true
13 |
14 | //是否禁止滑动
15 | fun setCanSwipe(canSwipe: Boolean) {
16 | this.canSwipe = canSwipe
17 | }
18 |
19 | override fun onTouchEvent(ev: MotionEvent?): Boolean {
20 | return canSwipe && super.onTouchEvent(ev)
21 | }
22 |
23 | override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
24 | return canSwipe && super.onInterceptTouchEvent(ev)
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/ReadMediaStore.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.ContentResolver
5 | import android.database.Cursor
6 | import android.net.Uri
7 | import android.provider.MediaStore
8 | import kotlinx.coroutines.Dispatchers
9 | import kotlinx.coroutines.withContext
10 | import org.json.JSONArray
11 | import org.json.JSONObject
12 |
13 |
14 | class ReadMediaStore {
15 | companion object {
16 | @SuppressLint("Recycle")
17 | fun start(contentResolver: ContentResolver): JSONArray {
18 | val cursor: Cursor = contentResolver.query(
19 | MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, null
20 | )!!
21 | val indexVideoId = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
22 | val indexVideoSize = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)
23 | val indexVideoTitle = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE)
24 | val indexVideoPath = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
25 | val indexVideoFolder =
26 | cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
27 | cursor.moveToPosition(-1)
28 | val array = JSONArray()
29 | while (cursor.moveToNext()) {
30 | val title = cursor.getString(indexVideoTitle)
31 | val size = cursor.getString(indexVideoSize)
32 | val path = cursor.getString(indexVideoPath)
33 | val videoUri = Uri.withAppendedPath(
34 | MediaStore.Video.Media.EXTERNAL_CONTENT_URI, cursor.getString(indexVideoId)
35 | )
36 | val folder = cursor.getString(indexVideoFolder)
37 | val itemJson = JSONObject()
38 | itemJson.put("title", title)
39 | itemJson.put("size", size)
40 | itemJson.put("path", path)
41 | itemJson.put("uri", videoUri.toString())
42 | itemJson.put("folder", folder)
43 | array.put(itemJson)
44 | }
45 | cursor.close()
46 | return array
47 | }
48 |
49 | suspend fun getFolder(contentResolver: ContentResolver): ArrayList {
50 | val array = ArrayList()
51 | withContext(Dispatchers.IO) {
52 | try {
53 | val cursor: Cursor = contentResolver.query(
54 | MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, null
55 | )!!
56 | val indexVideoFolder =
57 | cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
58 | cursor.moveToPosition(-1)
59 | while (cursor.moveToNext()) {
60 | val folder = cursor.getString(indexVideoFolder)?:"根目录"
61 | if (!array.contains(folder)) {
62 | if (folder.isNotEmpty()) {
63 | array.add(folder)
64 | }
65 | }
66 | }
67 | cursor.close()
68 | } catch (e: Exception) {
69 | array.add("")
70 | withContext(Dispatchers.Main) {
71 | //ToastUtils.show("文件所属加载错误")
72 | }
73 | }
74 | }
75 | return array
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/RefreshMediaStore.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.media.MediaScannerConnection
6 |
7 |
8 | class RefreshMediaStore {
9 | companion object {
10 | @Suppress("DEPRECATION")
11 | fun updateMedia(context: Context, path: String) {
12 | MediaScannerConnection.scanFile(
13 | context, arrayOf(path), null
14 | ) { _, uri ->
15 | val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
16 | mediaScanIntent.data = uri
17 | context.sendBroadcast(mediaScanIntent)
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/SeekBarAnim.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.animation.ValueAnimator
4 | import com.google.android.material.slider.Slider
5 |
6 | class SeekBarAnim {
7 | companion object {
8 | fun progressAnim(progress: Float, view: Slider) {
9 | val lastProgress: String = view.value.toString() + "f"
10 | val dh = ValueAnimator.ofFloat(lastProgress.toFloat(), progress)
11 | dh.duration = java.lang.String.valueOf(500).toLong()
12 | dh.addUpdateListener {
13 | val nowAnimatedValue = dh.animatedValue as Float
14 | if (nowAnimatedValue == progress) {
15 | dh.cancel()
16 | }
17 | view.value = nowAnimatedValue
18 | }
19 | dh.start()
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/SetBarTransparent.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import android.app.Activity
4 | import android.content.res.Resources
5 | import android.widget.LinearLayout
6 | import com.gyf.immersionbar.ImmersionBar
7 |
8 | class SetBarTransparent {
9 | companion object {
10 | fun setBarTransparent(statusBarView: LinearLayout, activity: Activity,resources: Resources) {
11 | ImmersionBar.with(activity).transparentBar().statusBarDarkFont(!IsNightMode.isNightMode(resources))
12 | .init()
13 | val statusBarHeight = ImmersionBar.getStatusBarHeight(activity)
14 | statusBarView.layoutParams.height = statusBarHeight
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/SettingsItemsUntil.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import com.tencent.mmkv.MMKV
4 |
5 | class SettingsItemsUntil {
6 | companion object {
7 | private val kV = MMKV.mmkvWithID("Setting")!!
8 | private val settings = arrayListOf(
9 | arrayListOf("darkMode", "0"),
10 | arrayListOf("isAutoPicture", "false"),
11 | arrayListOf("isDialogPlayer", "false"),
12 | arrayListOf("isScreenOn", "true"),
13 | arrayListOf("isAutoExit", "false")
14 | )
15 |
16 | fun writeSettingData(key: String, value: String) {
17 | kV.encode(key, value)
18 | }
19 |
20 | fun readSettingData(key: String): String? {
21 | return kV.decodeString(key)
22 | }
23 |
24 | fun fixItems() {
25 | for (index in 0 until settings.size) {
26 | if (kV.decodeString(settings[index][0]).isNullOrEmpty()) {
27 | kV.encode(settings[index][0], settings[index][1])
28 | }
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/SubStringX.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | class SubStringX {
4 | companion object{
5 | fun String.subStringX(beforeString: String?, afterString: String?): String? {
6 | return if (beforeString == null && afterString != null) {
7 | this.substring(0, this.indexOf(afterString))
8 | } else if (beforeString != null && afterString == null) {
9 | this.substring(this.indexOf(beforeString) + beforeString.length, this.length)
10 | } else if (beforeString != null && afterString != null) {
11 | this.subStringX(beforeString, null)!!.subStringX(null, afterString)
12 | } else {
13 | null
14 | }
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/clearpole/videoyou/utils/TimeParse.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou.utils
2 |
3 | import kotlin.math.roundToInt
4 |
5 | class TimeParse {
6 | companion object {
7 | fun timeParse(duration: Long): String? {
8 | var time: String? = ""
9 | val minute = duration / 60000
10 | val seconds = duration % 60000
11 | val second = (seconds.toFloat() / 1000).roundToInt().toLong()
12 | if (minute < 10) {
13 | time += "0"
14 | }
15 | time += "$minute:"
16 | if (second < 10) {
17 | time += "0"
18 | }
19 | time += second
20 | return time!!.trim()
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/res/anim/alpha_0_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/alpha_1_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ripple.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_arrow_back_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_arrow_back_small.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_auto_fix_high_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_cached_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_check_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_checklist_rtl_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_chevron_right_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_code_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_delete_forever_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_explore_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_extension_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_folder_open_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_format_list_bulleted_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_fullscreen_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_fullscreen_exit_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_gesture_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_hearing_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_help_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_home_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_keyboard_arrow_down_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_keyboard_arrow_right_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_lock_open_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_map_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_mark_unread_chat_alt_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_menu_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_note_add_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_notifications_none_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_pause_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_picture_in_picture_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_play_arrow_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_playlist_add_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_playlist_add_check_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_refresh_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_screen_rotation_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_search_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_settings_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_skip_next_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_skip_previous_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_web_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_webhook_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_wifi_tethering_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_auto_fix_high_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_chat_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_delete_forever_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_exit_to_app_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_explore_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_file_copy_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_gesture_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_hearing_disabled_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_light_mode_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_lock_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_mode_night_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_monetization_on_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/outline_speed_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/player_bottom_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/player_top_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/twotone_attach_file_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/twotone_drive_folder_upload_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/twotone_folder_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/video_player_toolbar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_error_crash.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
25 |
26 |
31 |
32 |
35 |
36 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
14 |
15 |
21 |
22 |
23 |
29 |
30 |
37 |
38 |
39 |
44 |
45 |
52 |
53 |
61 |
62 |
63 |
68 |
69 |
73 |
74 |
79 |
80 |
83 |
84 |
85 |
86 |
87 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_play_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
31 |
32 |
33 |
34 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
18 |
19 |
23 |
24 |
25 |
26 |
31 |
32 |
41 |
42 |
48 |
49 |
50 |
56 |
57 |
61 |
62 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
21 |
22 |
31 |
32 |
33 |
34 |
38 |
39 |
43 |
44 |
48 |
52 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_web_dav.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
30 |
31 |
32 |
33 |
37 |
38 |
42 |
43 |
51 |
52 |
62 |
63 |
64 |
70 |
71 |
74 |
75 |
80 |
81 |
82 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/app_is_activation.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/compose_videolist.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/compose_videoplayer.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/compose_videoslider.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/folder_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
24 |
25 |
29 |
30 |
33 |
38 |
45 |
46 |
47 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/folder_list_tree_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
10 |
11 |
12 |
15 |
16 |
21 |
22 |
30 |
31 |
40 |
41 |
46 |
47 |
48 |
59 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_drawer_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 |
22 |
31 |
32 |
40 |
47 |
51 |
57 |
63 |
68 |
69 |
75 |
81 |
86 |
87 |
88 |
89 |
97 |
103 |
109 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_page_folder.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
22 |
23 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_page_mediastore.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
15 |
16 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_page_playlist.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
15 |
16 |
26 |
27 |
31 |
32 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_page_setting.xml:
--------------------------------------------------------------------------------
1 |
2 | s
7 |
12 |
16 |
23 |
29 |
36 |
37 |
45 |
46 |
47 |
54 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_page_setting_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
21 |
29 |
36 |
37 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/material_dialog_edit_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/material_dialog_edit_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
22 |
23 |
24 |
32 |
33 |
38 |
39 |
40 |
49 |
50 |
55 |
56 |
57 |
65 |
66 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/media_store_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
27 |
28 |
33 |
34 |
35 |
44 |
45 |
54 |
55 |
63 |
64 |
65 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/play_list_name_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
23 |
28 |
29 |
30 |
40 |
41 |
49 |
50 |
59 |
60 |
61 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/play_list_videos_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
16 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/player_side_sheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/search_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
18 |
19 |
23 |
24 |
29 |
30 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/setting_about_do.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/setting_show.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/setting_theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
25 |
26 |
34 |
35 |
42 |
43 |
44 |
45 |
49 |
50 |
57 |
58 |
67 |
68 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/setting_theme_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
20 |
21 |
30 |
31 |
36 |
37 |
38 |
42 |
43 |
51 |
52 |
60 |
61 |
62 |
63 |
64 |
70 |
71 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/video_info_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
19 |
20 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/video_info_utils_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/webdav_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
27 |
28 |
35 |
36 |
44 |
45 |
46 |
55 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main_choose.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 |
18 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/playlist_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/video_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/webdav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/twox.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-hdpi/twox.gif
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | VideoYou
3 | 刷新媒体库
4 | 进入开发者调试
5 | 界面导航
6 | 主页
7 | 设置
8 | 功能
9 | 视频搜索
10 | 网络串流
11 | WebDav
12 | 已通知系统尝试刷新!\n这将需要数秒的时间\n请耐心等待...
13 | 本地没有播放列表
14 | 设置项目
15 | 更多
16 | 文件管理
17 | 隐私文件
18 | 播放时退出二次确认
19 | 在播放视频的时候退出会显示弹窗
20 | 深色模式
21 | 应用主题
22 | 崩溃了!\n我真的崩溃了!
23 | 离开播放器自动打开画中画
24 | 此功能仅限安卓9以上使用
25 | 播放界面常亮
26 | 播放界面屏幕永不自动熄灭
27 | 播放完毕自动退出
28 | 在播放完毕时自动退出
29 | 删除播放列表
30 | VideoPlayerActivity
31 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/com/clearpole/videoyou/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.clearpole.videoyou
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '8.1.0-alpha06' apply false
4 | id 'com.android.library' version '8.1.0-alpha06' apply false
5 | id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
6 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
24 | android.enableJetifier=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clearpole/VideoYou/ea93e09dee20d777dacd1942cca294e5aecf901c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jan 26 16:53:33 CST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenLocal()
6 | mavenCentral()
7 | maven { url 'https://jitpack.io' }
8 | maven { url 'https://repo1.maven.org/maven2/' }
9 | maven {
10 | url 'https://repo.huaweicloud.com/repository/maven/'
11 | }
12 | }
13 | }
14 | dependencyResolutionManagement {
15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
16 | repositories {
17 | gradlePluginPortal()
18 | google()
19 | mavenLocal()
20 | mavenCentral()
21 | maven { url 'https://jitpack.io' }
22 | maven { url 'https://repo1.maven.org/maven2/' }
23 | maven {
24 | url 'https://repo.huaweicloud.com/repository/maven/'
25 | }
26 | }
27 | }
28 | rootProject.name = "VideoYou - opt"
29 | include ':app'
30 |
--------------------------------------------------------------------------------