Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc-android
  • thresh/vlc-android
  • Dekans/vlc-android
  • robUx4/vlc-android
  • tguillem/vlc-android
  • Corbax/vlc-android
  • judeosby/vlc-android
  • chouquette/vlc-android
  • washingtonmurphy93/vlc-android
  • wipawanbeadklang540/vlc-android
  • xcorail/vlc-android
  • Aza/vlc-android
  • Skantes/vlc-android
  • filipjares/vlc-android
  • kazemihabib/vlc-android
  • amq10x/vlc-android
  • qadrian370/vlc-android
  • shivanshs9/vlc-android
  • vitaliyg2/vlc-android
  • orgads/vlc-android
  • rom1v/vlc-android
  • evidence/vlc-android
  • lk888/vlc-android
  • Klaus81/vlc-android
  • EwoutH/vlc-android
  • XilasZ/vlc-android
  • pawelpablo1975/vlc-android
  • uae2ae/vlc-android
  • Garf/vlc-android
  • abetatsunori7/vlc-android
  • ePirat/vlc-android
  • magsoft/vlc-android
  • quink/vlc-android
  • Ektos974/vlc-android
  • CymGen30/vlc-android
  • b1ue/vlc-android
  • alessiavalenti8/vlc-android
  • bars27101982/vlc-android
  • billybanda18/vlc-android
  • dklvip/vlc-android
  • sherylynn/vlc-android
  • ramcoach5/vlc-android
  • takise/vlc-android
  • peibolovedie/vlc-android
  • AMHeijboer/vlc-android
  • dahburj/vlc-android
  • gobennyb/vlc-android
  • masripmasrip824/vlc-android
  • bubu/vlc-android
  • tmk907/vlc-android
  • gorbahaaa/vlc-android
  • govind3321/vlc-android
  • jamieboyer42818/vlc-android
  • mrtakilapop/vlc-android
  • kazikarter90/vlc-android
  • chunyie771/vlc-android
  • nop404/vlc-android
  • hcalzazperz/vlc-android
  • zagwojtek69/vlc-android
  • nikonnick24/vlc-android
  • gmohiuddin215/vlc-android
  • stheinthan31/vlc-android
  • rogelioloreto29/vlc-android
  • philippestcyr5/vlc-android
  • Happyheather20/vlc-android
  • jimbobmcgee/vlc-android
  • mohwie/vlc-android
  • HeartBeat1608/vlc-android
  • jahan/vlc-android
  • Kevo1987/vlc-android
  • rrangel3584/vlc-android
  • xfridrich/vlc-android
  • devswami23/vlc-android
  • Isira-Seneviratne/vlc-android
  • PartyPhone22/vlc-android
  • kmajeshkrishnan/vlc-android
  • ramirotorresjr/vlc-android
  • aaronsalas469/vlc-android
  • arnan.np31/vlc-android
  • hkosacki/vlc-android
  • mg0691872/vlc-android
  • louregni/vlc-android
  • ritmapp/vlc-android
  • diegofn/vlc-android
  • s-ayush2903/vlc-android
  • chrisbohn1984/vlc-android
  • alexandre-janniaux/vlc-android
  • optimumpr/vlc-android
  • chirag-jn/vlc-android
  • e9ab98e991ab/vlc-android
  • suvDev/vlc-android
  • killthelord/vlc-android
  • Phoenix/vlc-android
  • soriyallc/vlc-android
  • tda1009/vlc-android
  • rhstone/vlc-android
  • ltnokiago/vlc-android
  • elbrujo1987/vlc-android
  • m1s4k1/vlc-android
  • mdc/vlc-android
  • arnaudj/vlc-android
  • abhinavmarwaha/vlc-android
  • dali546/vlc-android
  • Jeffset/vlc-android
  • megan30/vlc-android
  • lizhengdao/vlc-android
  • YajTPG/vlc-android
  • halcyon/vlc-android
  • ilya.yanok/vlc-android
  • jeramydhallmon/vlc-android
  • tijoemecano77/vlc-android
  • cjcj125125/vlc-android
  • dejan2609/vlc-android
  • JATIN2111999/vlc-android
  • imrohitkumar/vlc-android
  • sagudev/vlc-android
  • ILoveLin/vlc-android
  • tfighiera/vlc-android
  • snehil101/vlc-android
  • MKornelsen/vlc-android
  • m/vlc-android
  • core1024/vlc-android
  • vadimdolgachev/vlc-android
  • Kk77539/vlc-android
  • linzj/vlc-android
  • dantalian-pv/vlc-android
  • admkhalid/vlc-android
  • yaron/vlc-android
  • kn21091974/vlc-android
  • mylove1302/vlc-android
  • roblav96/vlc-android
  • alabiaga/vlc-android
  • kmnaveen101/vlc-android
  • nikiforoff1407/vlc-android
  • Android-Jester/vlc-android
  • frieda.rtwski/vlc-android
  • glaciers7506/vlc-android
  • rahul-gill/vlc-android
  • gaoxugang/vlc-android
  • Rishavgupta12345/vlc-android
  • dinho991556460/vlc-android
  • lighterowl/vlc-android
  • mary-kate/vlc-android
  • adnank20216/vlc-android
  • anthonylgutierrez79/vlc-android
  • Heliottw/vlc-android
  • mu1zix.ft3/vlc-android
  • yvesmaltais1212/vlc-android
  • ereme/vlc-android
  • jhonypalomino829/vlc-android
  • mx1up/vlc-android
  • sjwaddy/vlc-android
  • MohitMandalia/vlc-android
  • temaershov/vlc-android
  • js6pak/vlc-android
  • mishikallu/vlc-android
  • irfanmumtaz008/vlc-android
  • smurfohrachie/vlc-android
  • Goooler/vlc-android
  • eldo203050/vlc-android
  • dejesuszeus99/vlc-android
  • mfkl/vlc-android
  • Samfun75/vlc-android
  • markg85/vlc-android-ipfs
  • doktamelek911/vlc-android
  • wikwity/vlc-android
  • aangelmaker/vlc-android
  • krawczykradek119/vlc-android
  • ylz18180813163/vlc-android
  • galaxy9sx3/vlc-android
  • huajie2020/vlc-android
  • XuanTung95/vlc-android
  • kl/vlc-android
  • melihyolcu83/vlc-android
  • rt1shnik/vlc-android
  • jerryboy307/vlc-android
  • ikeuzochukwu6/vlc-android
  • patrikgolis/vlc-android
  • Ismavv/vlc-android
  • clementosumo/vlc-android
  • joshlamp66/vlc-android
  • nkmoyonyathiericyounge/vlc-android
  • DanTm99/vlc-android
  • Jeffrow41/vlc-android
  • fromphfr/vlc-android
  • 16project/vlc-android
  • Tomas8874/vlc-android
  • fixxxer87/vlc-android
  • sanjay/vlc-android
  • franciscojrp/vlc-android
  • cashellauswaus23/vlc-android
  • hengwu0/vlc-android
  • naythu2020rain/vlc-android
  • TongtengInhole/vlc-android
  • pupdoggy666/vlc-android
  • jcj921013/vlc-android
  • Gc6026/vlc-android
  • crijojc/vlc-android
  • mdrewight/vlc-android
  • davidhaywood0782/vlc-android
  • jbschtt/vlc-android
  • macfarlandcamel/vlc-android
  • syazairi/vlc-android
  • Commander01/vlc-android
  • baileyterry014/vlc-android
  • rodrickfranklin38/vlc-android
  • diego1245hernb/vlc-android
  • anton.canada/vlc-android
  • egazaekb/vlc-android
  • Marissa111113/vlc-android
  • jeinerbruno2/vlc-android
  • wehnie13/vlc-android
  • ozill87/vlc-android
  • legionfso/vlc-android
  • anazahirajoel/vlc-android
  • naomirojas1227/vlc-android
  • xbao/vlc-android
  • antoni.kozubek/vlc-android
  • pajela8482/vlc-android
  • karlfandango55/vlc-android
  • ruanbester07/vlc-android
  • chigita73/vlc-android
  • giu.pat6/vlc-android
  • Aura/vlc-android
  • marcwabo/vlc-android
  • contact.adgrafix/vlc-android
  • exlaverdad/vlc-android
  • simon.marquis88/vlc-android
  • youngkinsamantha421/vlc-android
  • edgard1161/vlc-android
  • agzx77/vlc-android
  • ha7204993/vlc-android
  • alghazwani.jar.6090/vlc-android
  • zrowton1206/vlc-android
  • darek1979513/vlc-android
  • matthiaskett18198/vlc-android
  • kubadyr77/vlc-android
  • romanstudeny1982/vlc-android
  • kumar107375/vlc-android
  • schong0525/vlc-android
  • Kt/vlc-android
  • jovelyn.esconde125/vlc-android
  • corriemacbarnard/vlc-android
  • apisbg91/vlc-android
  • yyusea/vlc-android
  • protechq88/vlc-android
  • rmangaraman/vlc-android
  • soutomikel/vlc-android
  • goregladaleksej5/vlc-android
  • tao/vlc-android
  • aruiz595/vlc-android
  • horvathpeter1202/vlc-android
  • litteh82/vlc-android
  • kerriochoa96/vlc-android
  • skshemul2022/vlc-android
  • popy/vlc-android
  • mizadpanahdev/vlc-android
  • pinarim2035/vlc-android
  • davidgooch1127/vlc-android
  • NyanCatTW1/vlc-android
  • Pendynurcahyo/vlc-android
  • fcartegnie/vlc-android
  • xiaoxiao921/vlc-android
  • rjtoell/vlc-android
  • devanshu6445/vlc-android
  • DopeDo69/vlc-android
  • quimsical/vlc-android
  • nickita.koltsoff/vlc-android
  • zeestander8617/vlc-android
  • alexsonarin06/vlc-android
  • minh189999h/vlc-android
  • JonnycatMeow/vlc-android
  • pup.ragnarok.1984/vlc-android2
  • jlcalderon13/vlc-android
  • franciszekk51214/vlc-android
  • yinsheng996/vlc-android
  • KenN3RD/vlc-android
  • leogps/vlc-android
  • alicuteo0407/vlc-android
  • MessirVoland/vlc-android
  • brett2uk/vlc-android
  • thomas.hermes/vlc-android
  • dgyudin/vlc-android
  • anuoshemohammad/vlc-android
  • r7truong/vlc-android
  • aaa1115910/vlc-android
  • arunkennedy78/vlc-android
  • nicholaszarra0069/vlc-android
  • georgipetrovdochev/vlc-android
  • Nikhil-z/vlc-android
  • misb1033/vlc-android
  • ktcoooot1/vlc-android
  • manmuc5/vlc-android
  • ahwhatisinttaken/vlc-android
  • m.nozka90/vlc-android
  • kabeermuhammad124319/vlc-android
  • ANGELONCE/vlc-android
  • manstabuk/vlc-android
  • yajcoca/vlc-android
  • dreamscell83/vlc-android
  • oldsssteveo/vlc-android
  • c0ff330k/vlc-android
  • ZhangXinmin528/vlc-android
  • lacsimarnald09/vlc-android
  • boykaisaac758/vlc-android
  • ooseidesmond/vlc-android
  • andresbott/vlc-android
  • yolandawanttoplay/vlc-android
  • lapaz17/vlc-android
  • sillyearl0138/vlc-android
  • NF-Repo/vlc-android
  • aaasg4001/vlc-android
  • mongia.puneet/vlc-android
  • slablaykon/vlc-android
  • Shabgardtanha1111/vlc-android
  • Benjamin_Loison/vlc-android
  • ashishami2002/vlc-android
  • Niram7777/vlc-android
  • Yashraj254/vlc-android
  • Choucroute_melba/vlc-android
  • Soete/vlc-android
  • MangalK/vlc-android
  • mohak2003/vlc-android
  • advait-0/vlc-android
  • McLP/vlc-android
  • fhuber/vlc-android
  • sami-sweng/vlc-android
  • josiahcarlson/vlc-android
  • mzych/vlc-android
329 results
Show changes
Showing
with 281 additions and 219 deletions
...@@ -16,46 +16,76 @@ ...@@ -16,46 +16,76 @@
android:summary="@string/tv_ui_summary" android:summary="@string/tv_ui_summary"
android:title="@string/tv_ui_title" /> android:title="@string/tv_ui_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="playback_speed"
android:summary="@string/playback_speed_summary"
android:title="@string/playback_speed_title" />
<ListPreference <ListPreference
android:defaultValue="" android:defaultValue=""
android:key="set_locale" android:key="set_locale"
android:title="@string/set_locale" /> android:title="@string/set_locale" />
<CheckBoxPreference
android:defaultValue="true"
android:key="resume_playback"
android:summary="@string/resume_playback_summary"
android:title="@string/resume_playback_title" />
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="true" android:defaultValue="true"
android:key="browser_show_all_files" android:key="browser_show_all_files"
android:summary="@string/browser_show_all_summary" android:summary="@string/browser_show_all_summary"
android:title="@string/browser_show_all_title" /> android:title="@string/browser_show_all_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="blurred_cover_background"
android:summary="@string/blurred_cover_background_summary"
android:title="@string/blurred_cover_background_title" />
<PreferenceCategory <PreferenceCategory
android:title="@string/interface_secondary_display_category_title" android:title="@string/video"
android:key="secondary_display_category"> android:key="ui_video_category">
<Preference
android:summary="@string/interface_secondary_display_category_summary"
android:key="secondary_display_category_summary" />
<ListPreference
android:defaultValue="-1"
android:entries="@array/video_min_group_length_list"
android:entryValues="@array/video_min_group_length_values"
android:key="video_min_group_length"
android:persistent="true"
android:summary="@string/video_min_group_length_summary"
android:title="@string/video_min_group_length_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="media_seen"
android:summary="@string/media_seen_summary"
android:title="@string/media_seen" />
<CheckBoxPreference
android:defaultValue="false"
android:key="force_play_all"
android:summary="@string/force_play_all_summary"
android:title="@string/force_play_all_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="force_list_portrait"
android:summary="@string/force_list_portrait_summary"
android:title="@string/force_list_portrait" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/audio"
android:key="ui_audio_category">
<CheckBoxPreference
android:defaultValue="true"
android:key="blurred_cover_background"
android:summary="@string/blurred_cover_background_summary"
android:title="@string/blurred_cover_background_title" />
<SwitchPreference
android:defaultValue="true"
android:key="audio_resume_card"
android:title="@string/audio_resume_card_title"
android:summary="@string/audio_resume_card_summary"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="lockscreen_cover"
android:summary="@string/lockscreen_cover_summary"
android:title="@string/lockscreen_cover_title" />
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="false" android:defaultValue="false"
android:key="enable_clone_mode" android:key="artists_show_all"
android:summary="@string/enable_clone_mode_summary" android:summary="@string/artists_show_all_summary"
android:title="@string/enable_clone_mode" /> android:title="@string/artists_show_all_title" />
<ListPreference
android:defaultValue="0"
android:entries="@array/audio_title_alignment_list"
android:entryValues="@array/audio_title_alignment_values"
android:key="audio_title_alignment"
android:persistent="true"
android:title="@string/audio_title_alignment" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>
...@@ -3,31 +3,6 @@ ...@@ -3,31 +3,6 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="video_category" android:key="video_category"
android:title="@string/video_prefs_category"> android:title="@string/video_prefs_category">
<ListPreference
android:defaultValue="6"
android:entries="@array/video_min_group_length_list"
android:entryValues="@array/video_min_group_length_values"
android:key="video_min_group_length"
android:persistent="true"
android:summary="@string/video_min_group_length_summary"
android:title="@string/video_min_group_length_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="media_seen"
android:summary="@string/media_seen_summary"
android:title="@string/media_seen" />
<CheckBoxPreference
android:defaultValue="false"
android:key="force_play_all"
android:summary="@string/force_play_all_summary"
android:title="@string/force_play_all_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="force_list_portrait"
android:summary="@string/force_list_portrait_summary"
android:title="@string/force_list_portrait" />
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="false" android:defaultValue="false"
android:key="save_brightness" android:key="save_brightness"
...@@ -38,6 +13,11 @@ ...@@ -38,6 +13,11 @@
android:key="save_individual_audio_delay" android:key="save_individual_audio_delay"
android:summary="@string/save_audiodelay_summary" android:summary="@string/save_audiodelay_summary"
android:title="@string/save_audiodelay_title" /> android:title="@string/save_audiodelay_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="playback_speed"
android:summary="@string/playback_speed_summary"
android:title="@string/playback_speed_title" />
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="true" android:defaultValue="true"
android:key="media_fast_seek" android:key="media_fast_seek"
...@@ -54,6 +34,11 @@ ...@@ -54,6 +34,11 @@
android:key="popup_force_legacy" android:key="popup_force_legacy"
android:summary="@string/popup_force_legacy_summary" android:summary="@string/popup_force_legacy_summary"
android:title="@string/popup_force_legacy_title" /> android:title="@string/popup_force_legacy_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="dialog_confirm_resume"
android:summary="@string/confirm_resume_summary"
android:title="@string/confirm_resume_title" />
<PreferenceCategory android:title="@string/controls_prefs_category"> <PreferenceCategory android:title="@string/controls_prefs_category">
<CheckBoxPreference <CheckBoxPreference
...@@ -71,11 +56,6 @@ ...@@ -71,11 +56,6 @@
android:key="enable_brightness_gesture" android:key="enable_brightness_gesture"
android:summary="@string/enable_brightness_gesture_summary" android:summary="@string/enable_brightness_gesture_summary"
android:title="@string/enable_brightness_gesture_title" /> android:title="@string/enable_brightness_gesture_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="dialog_confirm_resume"
android:summary="@string/confirm_resume_summary"
android:title="@string/confirm_resume_title" />
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="true" android:defaultValue="true"
android:key="enable_double_tap_seek" android:key="enable_double_tap_seek"
...@@ -93,4 +73,18 @@ ...@@ -93,4 +73,18 @@
android:title="@string/popup_keepscreen_title" /> android:title="@string/popup_keepscreen_title" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory
android:title="@string/interface_secondary_display_category_title"
android:key="secondary_display_category">
<Preference
android:summary="@string/interface_secondary_display_category_summary"
android:key="secondary_display_category_summary" />
<CheckBoxPreference
android:defaultValue="false"
android:key="enable_clone_mode"
android:summary="@string/enable_clone_mode_summary"
android:title="@string/enable_clone_mode" />
</PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>
...@@ -28,6 +28,7 @@ import android.content.res.Configuration ...@@ -28,6 +28,7 @@ import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import androidx.collection.SimpleArrayMap import androidx.collection.SimpleArrayMap
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
...@@ -86,6 +87,8 @@ class VLCApplication : Application() { ...@@ -86,6 +87,8 @@ class VLCApplication : Application() {
init { init {
instance = this instance = this
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
} }
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
......
...@@ -4,18 +4,14 @@ import android.content.SharedPreferences ...@@ -4,18 +4,14 @@ import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import org.videolan.vlc.gui.helpers.KeyHelper import org.videolan.tools.KeyHelper
import org.videolan.vlc.gui.helpers.applyTheme import org.videolan.vlc.gui.helpers.applyTheme
import org.videolan.vlc.util.Settings import org.videolan.vlc.util.Settings
open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() {
init {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
lateinit var settings: SharedPreferences lateinit var settings: SharedPreferences
......
...@@ -26,27 +26,20 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi ...@@ -26,27 +26,20 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.medialibrary.media.MediaWrapper import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.tools.MultiSelectAdapter
import org.videolan.tools.MultiSelectHelper
import org.videolan.vlc.databinding.HistoryItemBinding import org.videolan.vlc.databinding.HistoryItemBinding
import org.videolan.vlc.gui.helpers.SelectorViewHolder import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.vlc.gui.helpers.getMediaIconDrawable import org.videolan.vlc.gui.helpers.getMediaIconDrawable
import org.videolan.vlc.interfaces.IEventsHandler import org.videolan.vlc.interfaces.IEventsHandler
import org.videolan.vlc.util.UPDATE_SELECTION
import org.videolan.vlc.util.Util import org.videolan.vlc.util.Util
import java.util.*
@ObsoleteCoroutinesApi @ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
class HistoryAdapter(private val mEventsHandler: IEventsHandler) : DiffUtilAdapter<MediaWrapper, HistoryAdapter.ViewHolder>() { class HistoryAdapter(private val mEventsHandler: IEventsHandler) : DiffUtilAdapter<MediaWrapper, HistoryAdapter.ViewHolder>(), MultiSelectAdapter<MediaWrapper> {
private var mLayoutInflater: LayoutInflater? = null private var mLayoutInflater: LayoutInflater? = null
var multiSelectHelper: MultiSelectHelper<MediaWrapper> = MultiSelectHelper(this, UPDATE_SELECTION)
val selection: List<MediaWrapper>
get() {
val selection = LinkedList<MediaWrapper>()
for (media in dataset) {
if (media.hasStateFlags(MediaLibraryItem.FLAG_SELECTED))
selection.add(media)
}
return selection
}
inner class ViewHolder(binding: HistoryItemBinding) : SelectorViewHolder<HistoryItemBinding>(binding) { inner class ViewHolder(binding: HistoryItemBinding) : SelectorViewHolder<HistoryItemBinding>(binding) {
...@@ -83,17 +76,16 @@ class HistoryAdapter(private val mEventsHandler: IEventsHandler) : DiffUtilAdapt ...@@ -83,17 +76,16 @@ class HistoryAdapter(private val mEventsHandler: IEventsHandler) : DiffUtilAdapt
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val media = getItem(position) val media = getItem(position)
val isSelected = media.hasStateFlags(MediaLibraryItem.FLAG_SELECTED)
holder.binding.media = media holder.binding.media = media
holder.binding.cover = getMediaIconDrawable(holder.itemView.context, media.type) holder.binding.cover = getMediaIconDrawable(holder.itemView.context, media.type)
holder.selectView(isSelected) holder.selectView(multiSelectHelper.isSelected(position))
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: List<Any>) { override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: List<Any>) {
if (Util.isListEmpty(payloads)) if (Util.isListEmpty(payloads))
super.onBindViewHolder(holder, position, payloads) super.onBindViewHolder(holder, position, payloads)
else else
holder.selectView((payloads[0] as MediaLibraryItem).hasStateFlags(MediaLibraryItem.FLAG_SELECTED)) holder.selectView(multiSelectHelper.isSelected(position))
} }
override fun getItemId(arg0: Int): Long { override fun getItemId(arg0: Int): Long {
......
...@@ -34,6 +34,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi ...@@ -34,6 +34,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.medialibrary.media.MediaWrapper import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.tools.KeyHelper
import org.videolan.tools.MultiSelectHelper
import org.videolan.vlc.R import org.videolan.vlc.R
import org.videolan.vlc.gui.browser.MediaBrowserFragment import org.videolan.vlc.gui.browser.MediaBrowserFragment
import org.videolan.vlc.gui.helpers.UiTools import org.videolan.vlc.gui.helpers.UiTools
...@@ -50,6 +52,7 @@ private const val TAG = "VLC/HistoryFragment" ...@@ -50,6 +52,7 @@ private const val TAG = "VLC/HistoryFragment"
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHistory, SwipeRefreshLayout.OnRefreshListener, IEventsHandler { class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHistory, SwipeRefreshLayout.OnRefreshListener, IEventsHandler {
private lateinit var multiSelectHelper: MultiSelectHelper<MediaWrapper>
private val historyAdapter: HistoryAdapter = HistoryAdapter(this) private val historyAdapter: HistoryAdapter = HistoryAdapter(this)
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
...@@ -60,10 +63,12 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis ...@@ -60,10 +63,12 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(requireActivity(), HistoryModel.Factory(requireContext())).get(HistoryModel::class.java) viewModel = ViewModelProviders.of(requireActivity(), HistoryModel.Factory(requireContext())).get(HistoryModel::class.java)
viewModel.dataset.observe(this, Observer<List<MediaWrapper>> { list -> list?.let { viewModel.dataset.observe(this, Observer<List<MediaWrapper>> { list ->
historyAdapter.update(it) list?.let {
updateEmptyView() historyAdapter.update(it)
} }) updateEmptyView()
}
})
} }
override fun onStart() { override fun onStart() {
...@@ -79,6 +84,8 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis ...@@ -79,6 +84,8 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis
list.nextFocusLeftId = android.R.id.list list.nextFocusLeftId = android.R.id.list
list.nextFocusRightId = android.R.id.list list.nextFocusRightId = android.R.id.list
list.nextFocusForwardId = android.R.id.list list.nextFocusForwardId = android.R.id.list
multiSelectHelper = historyAdapter.multiSelectHelper
list.requestFocus() list.requestFocus()
registerForContextMenu(list) registerForContextMenu(list)
swipeRefreshLayout!!.setOnRefreshListener(this) swipeRefreshLayout!!.setOnRefreshListener(this)
...@@ -145,7 +152,7 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis ...@@ -145,7 +152,7 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis
} }
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
val selectionCount = historyAdapter.selection.size val selectionCount = multiSelectHelper.getSelectionCount()
if (selectionCount == 0) { if (selectionCount == 0) {
stopActionMode() stopActionMode()
return false return false
...@@ -156,7 +163,7 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis ...@@ -156,7 +163,7 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis
} }
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
val selection = historyAdapter.selection val selection = multiSelectHelper.getSelection()
if (selection.isNotEmpty()) { if (selection.isNotEmpty()) {
when (item.itemId) { when (item.itemId) {
R.id.action_history_play -> MediaUtils.openList(activity, selection, 0) R.id.action_history_play -> MediaUtils.openList(activity, selection, 0)
...@@ -174,19 +181,16 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis ...@@ -174,19 +181,16 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis
override fun onDestroyActionMode(mode: ActionMode) { override fun onDestroyActionMode(mode: ActionMode) {
actionMode = null actionMode = null
var index = -1 multiSelectHelper.clearSelection()
for (media in viewModel.dataset.value) {
++index
if (media.hasStateFlags(MediaLibraryItem.FLAG_SELECTED)) {
media.removeStateFlags(MediaLibraryItem.FLAG_SELECTED)
historyAdapter.notifyItemChanged(index, media)
}
}
} }
override fun onClick(v: View, position: Int, item: MediaLibraryItem) { override fun onClick(v: View, position: Int, item: MediaLibraryItem) {
if (KeyHelper.isShiftPressed && actionMode == null) {
onLongClick(v, position, item)
return
}
if (actionMode != null) { if (actionMode != null) {
item.toggleStateFlag(MediaLibraryItem.FLAG_SELECTED) multiSelectHelper.toggleSelection(position)
historyAdapter.notifyItemChanged(position, item) historyAdapter.notifyItemChanged(position, item)
invalidateActionMode() invalidateActionMode()
return return
...@@ -196,17 +200,13 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis ...@@ -196,17 +200,13 @@ class HistoryFragment : MediaBrowserFragment<HistoryModel>(), IRefreshable, IHis
} }
override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean { override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean {
if (actionMode != null) return false multiSelectHelper.toggleSelection(position, true)
item.toggleStateFlag(MediaLibraryItem.FLAG_SELECTED)
historyAdapter.notifyItemChanged(position, item) historyAdapter.notifyItemChanged(position, item)
startActionMode() if (actionMode == null) startActionMode()
invalidateActionMode()
return true return true
} }
override fun onShiftClick(v: View, layoutPosition: Int, item: MediaLibraryItem) {
if (actionMode != null) onClick(v, layoutPosition, item) else onLongClick(v, layoutPosition, item)
}
override fun onImageClick(v: View, position: Int, item: MediaLibraryItem) { override fun onImageClick(v: View, position: Int, item: MediaLibraryItem) {
if (actionMode != null) { if (actionMode != null) {
onClick(v, position, item) onClick(v, position, item)
......
...@@ -9,11 +9,13 @@ import android.os.Parcelable ...@@ -9,11 +9,13 @@ import android.os.Parcelable
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import kotlinx.coroutines.* import kotlinx.coroutines.*
...@@ -26,13 +28,14 @@ import org.videolan.medialibrary.media.MediaWrapper ...@@ -26,13 +28,14 @@ import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.vlc.R import org.videolan.vlc.R
import org.videolan.vlc.VLCApplication import org.videolan.vlc.VLCApplication
import org.videolan.vlc.databinding.InfoActivityBinding import org.videolan.vlc.databinding.InfoActivityBinding
import org.videolan.vlc.gui.browser.PathAdapter
import org.videolan.vlc.gui.browser.PathAdapterListener
import org.videolan.vlc.gui.helpers.AudioUtil import org.videolan.vlc.gui.helpers.AudioUtil
import org.videolan.vlc.gui.helpers.FloatingActionButtonBehavior import org.videolan.vlc.gui.helpers.FloatingActionButtonBehavior
import org.videolan.vlc.gui.video.MediaInfoAdapter import org.videolan.vlc.gui.video.MediaInfoAdapter
import org.videolan.vlc.media.MediaUtils import org.videolan.vlc.media.MediaUtils
import org.videolan.vlc.util.* import org.videolan.vlc.util.*
import java.io.File import java.io.File
import java.lang.Runnable
import java.util.* import java.util.*
private const val TAG = "VLC/InfoActivity" private const val TAG = "VLC/InfoActivity"
...@@ -40,11 +43,11 @@ private const val TAG_FAB_VISIBILITY = "FAB" ...@@ -40,11 +43,11 @@ private const val TAG_FAB_VISIBILITY = "FAB"
@ObsoleteCoroutinesApi @ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
class InfoActivity : AudioPlayerContainerActivity(), View.OnClickListener { class InfoActivity : AudioPlayerContainerActivity(), View.OnClickListener, PathAdapterListener {
private lateinit var item: MediaLibraryItem private lateinit var item: MediaLibraryItem
private lateinit var adapter: MediaInfoAdapter private lateinit var adapter: MediaInfoAdapter
private lateinit var model : InfoModel private lateinit var model: InfoModel
internal lateinit var binding: InfoActivityBinding internal lateinit var binding: InfoActivityBinding
...@@ -108,28 +111,57 @@ class InfoActivity : AudioPlayerContainerActivity(), View.OnClickListener { ...@@ -108,28 +111,57 @@ class InfoActivity : AudioPlayerContainerActivity(), View.OnClickListener {
if (length > 0) if (length > 0)
binding.length = Tools.millisToText(length) binding.length = Tools.millisToText(length)
if (item is MediaWrapper) {
val media = item as MediaWrapper
val resolution = generateResolutionClass(media.width, media.height)
binding.resolution = resolution
}
when { when {
item.itemType == MediaLibraryItem.TYPE_MEDIA -> { item.itemType == MediaLibraryItem.TYPE_MEDIA -> {
val media = item as MediaWrapper? val media = item as MediaWrapper
binding.path = Uri.decode(media!!.uri.path) // binding.path = Uri.decode(media!!.uri.path).replace("/", " > ")
binding.progress = if (media.length == 0L) 0 else (100.toLong() * media.time / length).toInt() binding.progress = if (media.length == 0L) 0 else (100.toLong() * media.time / length).toInt()
binding.sizeTitleText = getString(R.string.file_size) binding.sizeTitleText = getString(R.string.file_size)
if (isSchemeSupported(media.uri?.scheme)) {
binding.ariane.visibility = View.VISIBLE
binding.ariane.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
binding.ariane.adapter = PathAdapter(this, media)
if (binding.ariane.itemDecorationCount == 0) {
val did = DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL)
did.setDrawable(ContextCompat.getDrawable(this, R.drawable.ic_divider)!!)
binding.ariane.addItemDecoration(did)
}
} else binding.ariane.visibility = View.GONE
} }
item.itemType == MediaLibraryItem.TYPE_ARTIST -> { item.itemType == MediaLibraryItem.TYPE_ARTIST -> {
val albums = (item as Artist).albums val albums = (item as Artist).albums
val nbAlbums = albums?.size ?: 0 val nbAlbums = albums?.size ?: 0
binding.sizeTitleText = getString(R.string.albums) binding.sizeTitleText = getString(R.string.albums)
binding.sizeValueText = nbAlbums.toString() binding.sizeValueText = nbAlbums.toString()
binding.sizeIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_album))
binding.extraTitleText = getString(R.string.tracks) binding.extraTitleText = getString(R.string.tracks)
binding.extraValueText = nbTracks.toString() binding.extraValueText = nbTracks.toString()
binding.extraIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_song))
} }
else -> { else -> {
binding.sizeTitleText = getString(R.string.tracks) binding.sizeTitleText = getString(R.string.tracks)
binding.sizeValueText = nbTracks.toString() binding.sizeValueText = nbTracks.toString()
binding.sizeIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_song))
} }
} }
} }
override fun backTo(tag: String) {
}
override fun currentContext() = this
override fun showRoot() = false
override fun onPostCreate(savedInstanceState: Bundle?) { override fun onPostCreate(savedInstanceState: Bundle?) {
fragmentContainer = binding.container fragmentContainer = binding.container
super.onPostCreate(savedInstanceState) super.onPostCreate(savedInstanceState)
......
...@@ -176,15 +176,11 @@ open class PlaylistActivity : AudioPlayerContainerActivity(), IEventsHandler, IL ...@@ -176,15 +176,11 @@ open class PlaylistActivity : AudioPlayerContainerActivity(), IEventsHandler, IL
} }
override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean { override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean {
if (actionMode != null) return false audioBrowserAdapter.multiSelectHelper.toggleSelection(position, true)
audioBrowserAdapter.multiSelectHelper.toggleSelection(position) if (actionMode == null) startActionMode()
startActionMode()
return true return true
} }
override fun onShiftClick(v: View, layoutPosition: Int, item: MediaLibraryItem) {
if (actionMode != null) onClick(v, layoutPosition, item) else onLongClick(v, layoutPosition, item)
}
override fun onImageClick(v: View, position: Int, item: MediaLibraryItem) { override fun onImageClick(v: View, position: Int, item: MediaLibraryItem) {
if (actionMode != null) { if (actionMode != null) {
......
...@@ -48,7 +48,6 @@ import org.videolan.tools.MultiSelectHelper ...@@ -48,7 +48,6 @@ import org.videolan.tools.MultiSelectHelper
import org.videolan.vlc.R import org.videolan.vlc.R
import org.videolan.vlc.databinding.AudioBrowserCardItemBinding import org.videolan.vlc.databinding.AudioBrowserCardItemBinding
import org.videolan.vlc.databinding.AudioBrowserItemBinding import org.videolan.vlc.databinding.AudioBrowserItemBinding
import org.videolan.vlc.gui.helpers.KeyHelper
import org.videolan.vlc.gui.helpers.SelectorViewHolder import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.vlc.gui.helpers.getAudioIconDrawable import org.videolan.vlc.gui.helpers.getAudioIconDrawable
import org.videolan.vlc.gui.tv.FocusableRecyclerView import org.videolan.vlc.gui.tv.FocusableRecyclerView
...@@ -292,10 +291,7 @@ class AudioBrowserAdapter @JvmOverloads constructor(private val type: Int, priva ...@@ -292,10 +291,7 @@ class AudioBrowserAdapter @JvmOverloads constructor(private val type: Int, priva
fun onClick(v: View) { fun onClick(v: View) {
val item = getItem(layoutPosition) val item = getItem(layoutPosition)
if (item != null) if (item != null)
if (KeyHelper.isShiftPressed) mIEventsHandler.onClick(v, layoutPosition, item)
mIEventsHandler.onShiftClick(v, layoutPosition, item)
else
mIEventsHandler.onClick(v, layoutPosition, item)
} }
fun onMoreClick(v: View) { fun onMoreClick(v: View) {
......
...@@ -49,6 +49,7 @@ import androidx.recyclerview.widget.ItemTouchHelper ...@@ -49,6 +49,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.transition.AutoTransition import androidx.transition.AutoTransition
import androidx.transition.TransitionManager import androidx.transition.TransitionManager
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.* import kotlinx.coroutines.*
...@@ -99,6 +100,10 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -99,6 +100,10 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
private var headerTimeVisible = false private var headerTimeVisible = false
private var playerState = 0 private var playerState = 0
private var currentCoverArt: String? = null private var currentCoverArt: String? = null
private lateinit var pauseToPlay: AnimatedVectorDrawableCompat
private lateinit var playToPause: AnimatedVectorDrawableCompat
private lateinit var pauseToPlaySmall: AnimatedVectorDrawableCompat
private lateinit var playToPauseSmall: AnimatedVectorDrawableCompat
companion object { companion object {
private var DEFAULT_BACKGROUND_DARKER_ID = 0 private var DEFAULT_BACKGROUND_DARKER_ID = 0
...@@ -107,11 +112,14 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -107,11 +112,14 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
savedInstanceState?.let { playerState = it.getInt("player_state")} savedInstanceState?.let {
playerState = it.getInt("player_state")
wasPlaying = it.getBoolean("was_playing")
}
playlistAdapter = PlaylistAdapter(this) playlistAdapter = PlaylistAdapter(this)
settings = Settings.getInstance(requireContext()) settings = Settings.getInstance(requireContext())
playlistModel = PlaylistModel.get(this) playlistModel = PlaylistModel.get(this)
playlistModel.progress.observe(this@AudioPlayer, Observer { it?.let { updateProgress(it) } }) playlistModel.progress.observe(this@AudioPlayer, Observer { it?.let { updateProgress(it) } })
playlistModel.dataset.observe(this@AudioPlayer, playlistObserver) playlistModel.dataset.observe(this@AudioPlayer, playlistObserver)
playlistAdapter.setModel(playlistModel) playlistAdapter.setModel(playlistModel)
} }
...@@ -150,6 +158,12 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -150,6 +158,12 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
binding.showCover = settings.getBoolean("audio_player_show_cover", false) binding.showCover = settings.getBoolean("audio_player_show_cover", false)
binding.playlistSwitch.setImageResource(UiTools.getResourceFromAttribute(view.context, if (binding.showCover) R.attr.ic_playlist else R.attr.ic_playlist_on)) binding.playlistSwitch.setImageResource(UiTools.getResourceFromAttribute(view.context, if (binding.showCover) R.attr.ic_playlist else R.attr.ic_playlist_on))
binding.timeline.setOnSeekBarChangeListener(timelineListener) binding.timeline.setOnSeekBarChangeListener(timelineListener)
//For resizing purpose, we have to cache this twice even if it's from the same resource
playToPause = AnimatedVectorDrawableCompat.create(requireActivity(), R.drawable.anim_play_pause)!!
pauseToPlay = AnimatedVectorDrawableCompat.create(requireActivity(), R.drawable.anim_pause_play)!!
playToPauseSmall = AnimatedVectorDrawableCompat.create(requireActivity(), R.drawable.anim_play_pause)!!
pauseToPlaySmall = AnimatedVectorDrawableCompat.create(requireActivity(), R.drawable.anim_pause_play)!!
} }
override fun onResume() { override fun onResume() {
...@@ -160,11 +174,12 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -160,11 +174,12 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putInt("player_state", playerState) outState.putInt("player_state", playerState)
outState.putBoolean("was_playing", wasPlaying)
} }
private val ctxReceiver : CtxActionReceiver = object : CtxActionReceiver { private val ctxReceiver: CtxActionReceiver = object : CtxActionReceiver {
override fun onCtxAction(position: Int, option: Int) { override fun onCtxAction(position: Int, option: Int) {
when(option) { when (option) {
CTX_SET_RINGTONE -> AudioUtil.setRingtone(playlistAdapter.getItem(position), requireActivity()) CTX_SET_RINGTONE -> AudioUtil.setRingtone(playlistAdapter.getItem(position), requireActivity())
CTX_ADD_TO_PLAYLIST -> { CTX_ADD_TO_PLAYLIST -> {
val mw = playlistAdapter.getItem(position) val mw = playlistAdapter.getItem(position)
...@@ -201,15 +216,21 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -201,15 +216,21 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
updateBackground() updateBackground()
} }
private var wasPlaying = false private var wasPlaying = true
private fun updatePlayPause() { private fun updatePlayPause() {
val playing = playlistModel.playing val playing = playlistModel.playing
if (playing == wasPlaying) return
val imageResId = UiTools.getResourceFromAttribute(requireActivity(), if (playing) R.attr.ic_pause else R.attr.ic_play)
val text = getString(if (playing) R.string.pause else R.string.play) val text = getString(if (playing) R.string.pause else R.string.play)
binding.playPause.setImageResource(imageResId)
val drawable = if (playing) playToPause else pauseToPlay
val drawableSmall = if (playing) playToPauseSmall else pauseToPlaySmall
binding.playPause.setImageDrawable(drawable)
binding.headerPlayPause.setImageDrawable(drawableSmall)
if (playing != wasPlaying) {
drawable.start()
drawableSmall.start()
}
binding.playPause.contentDescription = text binding.playPause.contentDescription = text
binding.headerPlayPause.setImageResource(imageResId)
binding.headerPlayPause.contentDescription = text binding.headerPlayPause.contentDescription = text
wasPlaying = playing wasPlaying = playing
} }
...@@ -269,7 +290,8 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -269,7 +290,8 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
if (TextUtils.isEmpty(mw.artworkMrl)) { if (TextUtils.isEmpty(mw.artworkMrl)) {
setDefaultBackground() setDefaultBackground()
} else { } else {
val width = if (binding.contentLayout.width > 0) binding.contentLayout.width else activity?.getScreenWidth() ?: return@launch val width = if (binding.contentLayout.width > 0) binding.contentLayout.width else activity?.getScreenWidth()
?: return@launch
val blurredCover = withContext(Dispatchers.IO) { UiTools.blurBitmap(AudioUtil.readCoverBitmap(Uri.decode(mw.artworkMrl), width)) } val blurredCover = withContext(Dispatchers.IO) { UiTools.blurBitmap(AudioUtil.readCoverBitmap(Uri.decode(mw.artworkMrl), width)) }
if (!isStarted()) return@launch if (!isStarted()) return@launch
if (blurredCover !== null) { if (blurredCover !== null) {
...@@ -293,7 +315,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -293,7 +315,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
} }
override fun onSelectionSet(position: Int) { override fun onSelectionSet(position: Int) {
if (playerState != com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED && playerState != com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN) { if (playerState != BottomSheetBehavior.STATE_COLLAPSED && playerState != com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN) {
binding.songsList.scrollToPosition(position) binding.songsList.scrollToPosition(position)
} }
} }
...@@ -356,7 +378,6 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -356,7 +378,6 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
} }
} }
fun showAdvancedOptions(v: View) { fun showAdvancedOptions(v: View) {
if (!isVisible) return if (!isVisible) return
if (!this::optionsDelegate.isInitialized) { if (!this::optionsDelegate.isInitialized) {
...@@ -413,7 +434,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -413,7 +434,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
override fun beforeTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {} override fun beforeTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {}
fun backPressed() : Boolean { fun backPressed(): Boolean {
if (this::optionsDelegate.isInitialized && optionsDelegate.isShowing()) { if (this::optionsDelegate.isInitialized && optionsDelegate.isShowing()) {
optionsDelegate.hide() optionsDelegate.hide()
return true return true
...@@ -434,17 +455,17 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -434,17 +455,17 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
addTextChangedListener(this@AudioPlayer) addTextChangedListener(this@AudioPlayer)
} }
UiTools.setKeyboardVisibility(binding.playlistSearchText, false) UiTools.setKeyboardVisibility(binding.playlistSearchText, false)
if (playerState == com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED) setHeaderVisibilities(false, false, true, true, true, false) if (playerState == BottomSheetBehavior.STATE_COLLAPSED) setHeaderVisibilities(false, false, true, true, true, false)
else setHeaderVisibilities(true, true, false, false, false, true) else setHeaderVisibilities(true, true, false, false, false, true)
return true return true
} }
override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) { override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
val length = charSequence.length val length = charSequence.length
if (length > 1) { if (length > 0) {
playlistModel.filter(charSequence) playlistModel.filter(charSequence)
handler.removeCallbacks(hideSearchRunnable) handler.removeCallbacks(hideSearchRunnable)
} else if (length == 0) { } else {
playlistModel.filter(null) playlistModel.filter(null)
hideSearchField() hideSearchField()
} }
...@@ -560,7 +581,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -560,7 +581,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
override fun onStartTrackingTouch(seekBar: SeekBar) {} override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onProgressChanged(sb: SeekBar, progress: Int, fromUser: Boolean) { override fun onProgressChanged(sb: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
playlistModel.time = progress.toLong() playlistModel.time = progress.toLong()
binding.time.text = Tools.millisToString(if (showRemainingTime) progress - playlistModel.length else progress.toLong()) binding.time.text = Tools.millisToString(if (showRemainingTime) progress - playlistModel.length else progress.toLong())
binding.headerTime.text = Tools.millisToString(progress.toLong()) binding.headerTime.text = Tools.millisToString(progress.toLong())
...@@ -573,10 +594,10 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS ...@@ -573,10 +594,10 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, CoroutineS
override fun onMediaSwitching() {} override fun onMediaSwitching() {}
override fun onMediaSwitched(position: Int) { override fun onMediaSwitched(position: Int) {
when (position) { when (position) {
AudioMediaSwitcherListener.PREVIOUS_MEDIA -> playlistModel.previous(true) AudioMediaSwitcherListener.PREVIOUS_MEDIA -> playlistModel.previous(true)
AudioMediaSwitcherListener.NEXT_MEDIA -> playlistModel.next() AudioMediaSwitcherListener.NEXT_MEDIA -> playlistModel.next()
} }
} }
override fun onTouchClick() { override fun onTouchClick() {
......
...@@ -217,15 +217,11 @@ abstract class BaseAudioBrowser<T : SortableModel> : MediaBrowserFragment<T>(), ...@@ -217,15 +217,11 @@ abstract class BaseAudioBrowser<T : SortableModel> : MediaBrowserFragment<T>(),
} }
override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean { override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean {
if (actionMode != null) return false getCurrentAdapter()?.multiSelectHelper?.toggleSelection(position, true)
getCurrentAdapter()?.multiSelectHelper?.toggleSelection(position) if (actionMode == null) startActionMode()
startActionMode()
return true return true
} }
override fun onShiftClick(v: View, layoutPosition: Int, item: MediaLibraryItem) {
if (actionMode != null) onClick(v, layoutPosition, item) else onLongClick(v, layoutPosition, item)
}
override fun onImageClick(v: View, position: Int, item: MediaLibraryItem) { override fun onImageClick(v: View, position: Int, item: MediaLibraryItem) {
if (actionMode != null) { if (actionMode != null) {
......
...@@ -69,7 +69,7 @@ private const val MSG_REFRESH = 3 ...@@ -69,7 +69,7 @@ private const val MSG_REFRESH = 3
@ObsoleteCoroutinesApi @ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefreshable, SwipeRefreshLayout.OnRefreshListener, View.OnClickListener, IEventsHandler, CtxActionReceiver { abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefreshable, SwipeRefreshLayout.OnRefreshListener, View.OnClickListener, IEventsHandler, CtxActionReceiver, PathAdapterListener {
protected val handler = BrowserFragmentHandler(this) protected val handler = BrowserFragmentHandler(this)
private lateinit var layoutManager: LinearLayoutManager private lateinit var layoutManager: LinearLayoutManager
...@@ -85,7 +85,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -85,7 +85,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
protected lateinit var binding: DirectoryBrowserBinding protected lateinit var binding: DirectoryBrowserBinding
protected lateinit var browserFavRepository: BrowserFavRepository protected lateinit var browserFavRepository: BrowserFavRepository
protected abstract fun createFragment(): Fragment protected abstract fun createFragment(): Fragment
protected abstract fun browseRoot() protected abstract fun browseRoot()
...@@ -146,17 +145,20 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -146,17 +145,20 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
ariane.adapter = PathAdapter(this, media) ariane.adapter = PathAdapter(this, media)
if (ariane.itemDecorationCount == 0) { if (ariane.itemDecorationCount == 0) {
val did = DividerItemDecoration(requireContext(), DividerItemDecoration.HORIZONTAL) val did = DividerItemDecoration(requireContext(), DividerItemDecoration.HORIZONTAL)
did.setDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.divider_grey_50_18dp)!!) did.setDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_divider)!!)
ariane.addItemDecoration(did) ariane.addItemDecoration(did)
} }
ariane.scrollToPosition(ariane.adapter!!.itemCount - 1) ariane.scrollToPosition(ariane.adapter!!.itemCount - 1)
} else ariane.visibility = View.GONE } else ariane.visibility = View.GONE
} }
fun backTo(tag: String) { override fun backTo(tag: String) {
requireActivity().supportFragmentManager.popBackStack(tag, FragmentManager.POP_BACK_STACK_INCLUSIVE) requireActivity().supportFragmentManager.popBackStack(tag, FragmentManager.POP_BACK_STACK_INCLUSIVE)
} }
override fun currentContext() = requireContext()
override fun showRoot() = true
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
...@@ -184,14 +186,12 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -184,14 +186,12 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
} }
override fun getTitle(): String = when { override fun getTitle(): String = when {
isRootDirectory -> categoryTitle isRootDirectory -> categoryTitle
currentMedia != null -> currentMedia!!.title currentMedia != null -> currentMedia!!.title
else -> mrl ?: "" else -> mrl ?: ""
} }
override val subTitle: String? = override val subTitle: String? =
if (isRootDirectory) null else { if (isRootDirectory) null else {
var mrl = mrl?.removeFileProtocole() ?: "" var mrl = mrl?.removeFileProtocole() ?: ""
...@@ -203,7 +203,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -203,7 +203,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
if (currentMedia != null) mrl else null if (currentMedia != null) mrl else null
} }
fun goBack(): Boolean { fun goBack(): Boolean {
val activity = activity ?: return false val activity = activity ?: return false
if (!isRootDirectory) activity.supportFragmentManager.popBackStack() if (!isRootDirectory) activity.supportFragmentManager.popBackStack()
...@@ -281,7 +280,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -281,7 +280,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
override fun clear() = adapter.clear() override fun clear() = adapter.clear()
override fun removeItem(item: MediaLibraryItem): Boolean { override fun removeItem(item: MediaLibraryItem): Boolean {
val view = view ?: return false val view = view ?: return false
...@@ -389,6 +387,8 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -389,6 +387,8 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
} }
override fun onClick(v: View, position: Int, item: MediaLibraryItem) { override fun onClick(v: View, position: Int, item: MediaLibraryItem) {
val mediaWrapper = item as MediaWrapper val mediaWrapper = item as MediaWrapper
if (actionMode != null) { if (actionMode != null) {
if (mediaWrapper.type == MediaWrapper.TYPE_AUDIO || if (mediaWrapper.type == MediaWrapper.TYPE_AUDIO ||
...@@ -405,22 +405,17 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -405,22 +405,17 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
} }
override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean { override fun onLongClick(v: View, position: Int, item: MediaLibraryItem): Boolean {
if (actionMode != null || item.itemType != MediaLibraryItem.TYPE_MEDIA) return false if (item.itemType != MediaLibraryItem.TYPE_MEDIA) return false
val mediaWrapper = item as MediaWrapper val mediaWrapper = item as MediaWrapper
if (mediaWrapper.type == MediaWrapper.TYPE_AUDIO || if (mediaWrapper.type == MediaWrapper.TYPE_AUDIO ||
mediaWrapper.type == MediaWrapper.TYPE_VIDEO || mediaWrapper.type == MediaWrapper.TYPE_VIDEO ||
mediaWrapper.type == MediaWrapper.TYPE_DIR) { mediaWrapper.type == MediaWrapper.TYPE_DIR) {
if (actionMode != null) return false adapter.multiSelectHelper.toggleSelection(position, true)
adapter.multiSelectHelper.toggleSelection(position) if (actionMode == null) startActionMode()
startActionMode()
} else onCtxClick(v, position, item) } else onCtxClick(v, position, item)
return true return true
} }
override fun onShiftClick(v: View, layoutPosition: Int, item: MediaLibraryItem) {
if (actionMode != null) onClick(v, layoutPosition, item) else onLongClick(v, layoutPosition, item)
}
override fun onCtxClick(v: View, position: Int, item: MediaLibraryItem) { override fun onCtxClick(v: View, position: Int, item: MediaLibraryItem) {
if (actionMode == null && item.itemType == MediaLibraryItem.TYPE_MEDIA) launch { if (actionMode == null && item.itemType == MediaLibraryItem.TYPE_MEDIA) launch {
val mw = item as MediaWrapper val mw = item as MediaWrapper
...@@ -451,7 +446,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -451,7 +446,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
} }
} }
override fun onCtxAction(position: Int, option: Int) { override fun onCtxAction(position: Int, option: Int) {
val mw = adapter.getItem(position) as? MediaWrapper ?: return val mw = adapter.getItem(position) as? MediaWrapper ?: return
when (option) { when (option) {
...@@ -500,7 +494,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr ...@@ -500,7 +494,6 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
} }
override fun onItemFocused(v: View, item: MediaLibraryItem) { override fun onItemFocused(v: View, item: MediaLibraryItem) {
} }
private fun updateFab() { private fun updateFab() {
......
package org.videolan.vlc.gui.browser package org.videolan.vlc.gui.browser
import android.content.Context
import android.net.Uri import android.net.Uri
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
...@@ -13,15 +14,15 @@ import org.videolan.vlc.util.AndroidDevices ...@@ -13,15 +14,15 @@ import org.videolan.vlc.util.AndroidDevices
private val storages = SimpleArrayMap<String, String>() private val storages = SimpleArrayMap<String, String>()
class PathAdapter(val browser: BaseBrowserFragment, media: MediaWrapper) : RecyclerView.Adapter<PathAdapter.ViewHolder>() { class PathAdapter(val browser: PathAdapterListener, media: MediaWrapper) : RecyclerView.Adapter<PathAdapter.ViewHolder>() {
init { init {
if (media.hasStateFlags(MediaLibraryItem.FLAG_STORAGE)) storages.put(Uri.decode(media.uri.path), media.title) if (media.hasStateFlags(MediaLibraryItem.FLAG_STORAGE)) storages.put(Uri.decode(media.uri.path), media.title)
} }
private val memoryTitle = browser.getString(R.string.internal_memory) private val memoryTitle = browser.currentContext().getString(R.string.internal_memory)
private val browserTitle = browser.getString(R.string.browser) private val browserTitle = browser.currentContext().getString(R.string.browser)
private val otgDevice = browser.getString(R.string.otg_device_title) private val otgDevice = browser.currentContext().getString(R.string.otg_device_title)
private val segments = prepareSegments(Uri.decode(media.uri.path)) private val segments = prepareSegments(Uri.decode(media.uri.path))
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
...@@ -52,7 +53,7 @@ class PathAdapter(val browser: BaseBrowserFragment, media: MediaWrapper) : Recyc ...@@ -52,7 +53,7 @@ class PathAdapter(val browser: BaseBrowserFragment, media: MediaWrapper) : Recyc
path.startsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY) -> path.replace(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY, memoryTitle) path.startsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY) -> path.replace(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY, memoryTitle)
else -> replaceStoragePath(path) else -> replaceStoragePath(path)
} }
val list = mutableListOf(browserTitle) val list = if (browser.showRoot()) mutableListOf(browserTitle) else mutableListOf()
if (isOtg) list.add(otgDevice) if (isOtg) list.add(otgDevice)
list.addAll(string.split('/').filter { !it.isEmpty() }) list.addAll(string.split('/').filter { !it.isEmpty() })
return list return list
...@@ -65,4 +66,10 @@ class PathAdapter(val browser: BaseBrowserFragment, media: MediaWrapper) : Recyc ...@@ -65,4 +66,10 @@ class PathAdapter(val browser: BaseBrowserFragment, media: MediaWrapper) : Recyc
} }
return path return path
} }
}
interface PathAdapterListener {
fun backTo(tag: String)
fun currentContext(): Context
fun showRoot(): Boolean
} }
\ No newline at end of file
...@@ -56,7 +56,7 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener, ...@@ -56,7 +56,7 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener,
private lateinit var mListView: RecyclerView private lateinit var mListView: RecyclerView
private lateinit var mEmptyView: TextView private lateinit var mEmptyView: TextView
private lateinit var mSaveButton: Button private lateinit var mSaveButton: Button
private lateinit var mAdapter: SimpleAdapter private lateinit var adapter: SimpleAdapter
private lateinit var mTracks: Array<MediaWrapper> private lateinit var mTracks: Array<MediaWrapper>
private lateinit var mNewTrack: Array<MediaWrapper> private lateinit var mNewTrack: Array<MediaWrapper>
private lateinit var mMedialibrary: Medialibrary private lateinit var mMedialibrary: Medialibrary
...@@ -67,7 +67,7 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener, ...@@ -67,7 +67,7 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener,
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mMedialibrary = VLCApplication.mlInstance mMedialibrary = VLCApplication.mlInstance
mAdapter = SimpleAdapter(this) adapter = SimpleAdapter(this)
mTracks = try { mTracks = try {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
arguments!!.getParcelableArray(KEY_TRACKS) as Array<MediaWrapper> arguments!!.getParcelableArray(KEY_TRACKS) as Array<MediaWrapper>
...@@ -99,14 +99,14 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener, ...@@ -99,14 +99,14 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener,
mEditText!!.setOnEditorActionListener(this) mEditText!!.setOnEditorActionListener(this)
mListView.layoutManager = LinearLayoutManager(view.context) mListView.layoutManager = LinearLayoutManager(view.context)
mListView.adapter = mAdapter mListView.adapter = adapter
mAdapter.submitList(Arrays.asList<MediaLibraryItem>(*mMedialibrary.playlists)) adapter.submitList(Arrays.asList<MediaLibraryItem>(*mMedialibrary.playlists))
updateEmptyView() updateEmptyView()
} }
private fun updateEmptyView() { private fun updateEmptyView() {
mEmptyView.visibility = if (mAdapter.isEmpty()) View.VISIBLE else View.GONE mEmptyView.visibility = if (adapter.isEmpty()) View.VISIBLE else View.GONE
} }
override fun onClick(v: View) { override fun onClick(v: View) {
......
package org.videolan.vlc.gui.dialogs package org.videolan.vlc.gui.dialogs
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
...@@ -20,12 +21,12 @@ import org.videolan.vlc.viewmodels.SubtitlesModel ...@@ -20,12 +21,12 @@ import org.videolan.vlc.viewmodels.SubtitlesModel
class SubtitleDownloadFragment : Fragment() { class SubtitleDownloadFragment : Fragment() {
private lateinit var viewModel: SubtitlesModel private lateinit var viewModel: SubtitlesModel
private lateinit var adapter: SubtitlesAdapter private lateinit var adapter: SubtitlesAdapter
lateinit var mediaPath: String lateinit var mediaUri: Uri
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mediaPath = arguments?.getString(MEDIA_PATH, "") ?: "" mediaUri = arguments?.getParcelable(MEDIA_PATH) ?: Uri.EMPTY
viewModel = ViewModelProviders.of(requireActivity(), SubtitlesModel.Factory(requireContext(), mediaPath)).get(mediaPath, SubtitlesModel::class.java) viewModel = ViewModelProviders.of(requireActivity(), SubtitlesModel.Factory(requireContext(), mediaUri)).get(mediaUri.path, SubtitlesModel::class.java)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...@@ -75,9 +76,9 @@ class SubtitleDownloadFragment : Fragment() { ...@@ -75,9 +76,9 @@ class SubtitleDownloadFragment : Fragment() {
} }
companion object { companion object {
fun newInstance(mediaPath: String): SubtitleDownloadFragment { fun newInstance(mediaUri: Uri): SubtitleDownloadFragment {
val subtitleDownloadFragment = SubtitleDownloadFragment() val subtitleDownloadFragment = SubtitleDownloadFragment()
subtitleDownloadFragment.arguments = Bundle(1).apply { putString(MEDIA_PATH, mediaPath) } subtitleDownloadFragment.arguments = Bundle(1).apply { putParcelable(MEDIA_PATH, mediaUri) }
return subtitleDownloadFragment return subtitleDownloadFragment
} }
} }
......
...@@ -34,26 +34,22 @@ const val MEDIA_PATH = "MEDIA_PATH" ...@@ -34,26 +34,22 @@ const val MEDIA_PATH = "MEDIA_PATH"
@ObsoleteCoroutinesApi @ObsoleteCoroutinesApi
class SubtitleDownloaderDialogFragment : DialogFragment() { class SubtitleDownloaderDialogFragment : DialogFragment() {
private lateinit var adapter: ViewPagerAdapter private lateinit var adapter: ViewPagerAdapter
private lateinit var paths: List<String> private lateinit var uris: List<Uri>
private lateinit var viewModel: SubtitlesModel private lateinit var viewModel: SubtitlesModel
private lateinit var toast: Toast private lateinit var toast: Toast
val listEventActor = coroutineScope.actor<SubtitleEvent> { val listEventActor = coroutineScope.actor<SubtitleEvent> {
for (subtitleEvent in channel) if (isActive) when (subtitleEvent) { for (subtitleEvent in channel) if (isActive) when (subtitleEvent) {
is Click -> when (subtitleEvent.item.state) { is Click -> when (subtitleEvent.item.state) {
State.NotDownloaded -> VLCDownloadManager.download(context!!, subtitleEvent.item) State.NotDownloaded -> VLCDownloadManager.download(requireActivity(), subtitleEvent.item)
State.Downloaded -> deleteSubtitleDialog(requireActivity(), DialogInterface.OnClickListener { _, _ -> viewModel.deleteSubtitle(subtitleEvent.item.mediaPath, subtitleEvent.item.idSubtitle) } State.Downloaded -> deleteSubtitleDialog(requireActivity(), DialogInterface.OnClickListener { _, _ -> viewModel.deleteSubtitle(subtitleEvent.item.mediaUri.path, subtitleEvent.item.idSubtitle) }
, DialogInterface.OnClickListener { _, _ -> }) , DialogInterface.OnClickListener { _, _ -> })
else -> return@actor else -> return@actor
} }
is LongClick -> { is LongClick -> {
@StringRes val message = when (subtitleEvent.item.state) { @StringRes val message = when (subtitleEvent.item.state) {
State.NotDownloaded -> { State.NotDownloaded -> R.string.download_the_selected
R.string.download_the_selected State.Downloaded -> R.string.delete_the_selected
}
State.Downloaded -> {
R.string.delete_the_selected
}
// Todo else -> {"Cancel download"} // Todo else -> {"Cancel download"}
else -> return@actor else -> return@actor
} }
...@@ -68,29 +64,29 @@ class SubtitleDownloaderDialogFragment : DialogFragment() { ...@@ -68,29 +64,29 @@ class SubtitleDownloaderDialogFragment : DialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
paths = savedInstanceState?.getStringArrayList(MEDIA_PATHS)?.toList() uris = savedInstanceState?.getParcelableArrayList<Uri>(MEDIA_PATHS)?.toList()
?: arguments?.getStringArrayList(MEDIA_PATHS)?.toList() ?: listOf() ?: arguments?.getParcelableArrayList<Uri>(MEDIA_PATHS)?.toList() ?: listOf()
if (paths.isEmpty()) dismiss() if (uris.isEmpty()) dismiss()
viewModel = ViewModelProviders.of(requireActivity(), SubtitlesModel.Factory(requireContext(), paths[0])).get(paths[0], SubtitlesModel::class.java) viewModel = ViewModelProviders.of(requireActivity(), SubtitlesModel.Factory(requireContext(), uris[0])).get(uris[0].path, SubtitlesModel::class.java)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
val binding = SubtitleDownloaderDialogBinding.inflate(inflater, container, false) val binding = SubtitleDownloaderDialogBinding.inflate(inflater, container, false)
adapter = ViewPagerAdapter(requireContext(), childFragmentManager, paths) adapter = ViewPagerAdapter(requireContext(), childFragmentManager, uris)
binding.pager.adapter = adapter binding.pager.adapter = adapter
binding.tabLayout.setupWithViewPager(binding.pager) binding.tabLayout.setupWithViewPager(binding.pager)
if (paths.size < 2) binding.nextButton.visibility = View.GONE if (uris.size < 2) binding.nextButton.visibility = View.GONE
binding.nextButton.setOnClickListener { binding.nextButton.setOnClickListener {
if (paths.size > 1) if (uris.size > 1)
MediaUtils.showSubtitleDownloaderDialogFragment(requireActivity(), paths.takeLast(paths.size - 1)) MediaUtils.showSubtitleDownloaderDialogFragment(requireActivity(), uris.takeLast(uris.size - 1))
dismiss() dismiss()
} }
binding.movieName.text = Uri.parse(paths[0]).lastPathSegment binding.movieName.text = uris[0].lastPathSegment
return binding.root return binding.root
} }
...@@ -101,14 +97,14 @@ class SubtitleDownloaderDialogFragment : DialogFragment() { ...@@ -101,14 +97,14 @@ class SubtitleDownloaderDialogFragment : DialogFragment() {
// android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" // android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
// so dialog size breaks on orientation // so dialog size breaks on orientation
if (requireActivity() is VideoPlayerActivity) { if (requireActivity() is VideoPlayerActivity) {
MediaUtils.showSubtitleDownloaderDialogFragment(requireActivity(), paths) MediaUtils.showSubtitleDownloaderDialogFragment(requireActivity(), uris)
dismiss() dismiss()
} }
} }
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putStringArrayList(MEDIA_PATHS, ArrayList(paths)) outState.putParcelableArrayList(MEDIA_PATHS, ArrayList(uris))
} }
override fun onDestroy() { override fun onDestroy() {
...@@ -117,23 +113,23 @@ class SubtitleDownloaderDialogFragment : DialogFragment() { ...@@ -117,23 +113,23 @@ class SubtitleDownloaderDialogFragment : DialogFragment() {
} }
companion object { companion object {
fun newInstance(mediaPaths: List<String>): SubtitleDownloaderDialogFragment { fun newInstance(mediaUris: List<Uri>): SubtitleDownloaderDialogFragment {
val subtitleDownloaderDialogFragment = SubtitleDownloaderDialogFragment() val subtitleDownloaderDialogFragment = SubtitleDownloaderDialogFragment()
val args = Bundle().apply { putStringArrayList(MEDIA_PATHS, ArrayList(mediaPaths)) } val args = Bundle().apply { putParcelableArrayList(MEDIA_PATHS, ArrayList(mediaUris)) }
subtitleDownloaderDialogFragment.arguments = args subtitleDownloaderDialogFragment.arguments = args
return subtitleDownloaderDialogFragment return subtitleDownloaderDialogFragment
} }
} }
class ViewPagerAdapter(context: Context, fragmentManager: FragmentManager, private val paths: List<String>) : FragmentPagerAdapter(fragmentManager) { class ViewPagerAdapter(context: Context, fragmentManager: FragmentManager, private val uris: List<Uri>) : FragmentPagerAdapter(fragmentManager) {
private val tabTitles = arrayOf(context.getString(R.string.download), context.getString(R.string.history)) private val tabTitles = arrayOf(context.getString(R.string.download), context.getString(R.string.history))
override fun getPageTitle(position: Int): String? = tabTitles[position] override fun getPageTitle(position: Int): String? = tabTitles[position]
override fun getItem(position: Int) = when (position) { override fun getItem(position: Int) = when (position) {
0 -> SubtitleDownloadFragment.newInstance(paths[0]) 0 -> SubtitleDownloadFragment.newInstance(uris[0])
else -> SubtitleHistoryFragment.newInstance(paths[0]) else -> SubtitleHistoryFragment.newInstance(uris[0])
} }
override fun getCount() = 2 override fun getCount() = 2
......
package org.videolan.vlc.gui.dialogs package org.videolan.vlc.gui.dialogs
import androidx.lifecycle.Observer import android.net.Uri
import androidx.lifecycle.ViewModelProviders
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import org.videolan.vlc.databinding.SubtitleHistoryFragmentBinding import org.videolan.vlc.databinding.SubtitleHistoryFragmentBinding
...@@ -15,12 +16,12 @@ import org.videolan.vlc.viewmodels.SubtitlesModel ...@@ -15,12 +16,12 @@ import org.videolan.vlc.viewmodels.SubtitlesModel
class SubtitleHistoryFragment : Fragment() { class SubtitleHistoryFragment : Fragment() {
private lateinit var viewModel: SubtitlesModel private lateinit var viewModel: SubtitlesModel
private lateinit var adapter: SubtitlesAdapter private lateinit var adapter: SubtitlesAdapter
lateinit var mediaPath: String lateinit var mediaUri: Uri
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mediaPath = arguments?.getString(MEDIA_PATH, "") ?: "" mediaUri = arguments?.getParcelable(MEDIA_PATH) ?: Uri.EMPTY
viewModel = ViewModelProviders.of(requireActivity(), SubtitlesModel.Factory(requireContext(), mediaPath)).get(mediaPath, SubtitlesModel::class.java) viewModel = ViewModelProviders.of(requireActivity(), SubtitlesModel.Factory(requireContext(), mediaUri)).get(mediaUri.path, SubtitlesModel::class.java)
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...@@ -40,9 +41,9 @@ class SubtitleHistoryFragment : Fragment() { ...@@ -40,9 +41,9 @@ class SubtitleHistoryFragment : Fragment() {
} }
companion object { companion object {
fun newInstance(mediaPath: String): SubtitleHistoryFragment { fun newInstance(mediaUri: Uri): SubtitleHistoryFragment {
val subtitleHistoryFragment = SubtitleHistoryFragment() val subtitleHistoryFragment = SubtitleHistoryFragment()
subtitleHistoryFragment.arguments = Bundle(1).apply { putString(MEDIA_PATH, mediaPath) } subtitleHistoryFragment.arguments = Bundle(1).apply { putParcelable(MEDIA_PATH, mediaUri) }
return subtitleHistoryFragment return subtitleHistoryFragment
} }
} }
......
package org.videolan.vlc.gui.dialogs package org.videolan.vlc.gui.dialogs
import android.net.Uri
data class SubtitleItem ( data class SubtitleItem (
val idSubtitle: String, val idSubtitle: String,
val mediaPath: String, val mediaUri: Uri,
val subLanguageID: String, val subLanguageID: String,
val movieReleaseName: String, val movieReleaseName: String,
val state: State, val state: State,
val zipDownloadLink: String val zipDownloadLink: String
) )
enum class State { enum class State {
......
...@@ -3,7 +3,6 @@ package org.videolan.vlc.gui.dialogs ...@@ -3,7 +3,6 @@ package org.videolan.vlc.gui.dialogs
import android.content.DialogInterface import android.content.DialogInterface
import android.content.res.Configuration import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import android.view.ContextThemeWrapper
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
...@@ -20,14 +19,21 @@ import org.videolan.vlc.util.Settings ...@@ -20,14 +19,21 @@ import org.videolan.vlc.util.Settings
abstract class VLCBottomSheetDialogFragment : BottomSheetDialogFragment() { abstract class VLCBottomSheetDialogFragment : BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
if (Settings.showTvUi) {
requireActivity().setTheme(R.style.Theme_VLC_Black)
}
super.onCreate(savedInstanceState)
}
var onDismissListener: DialogInterface.OnDismissListener? = null var onDismissListener: DialogInterface.OnDismissListener? = null
fun inflate(inflater: LayoutInflater, container: ViewGroup?, @LayoutRes layout: Int): View? { fun inflate(inflater: LayoutInflater, container: ViewGroup?, @LayoutRes layout: Int): View? {
if (Settings.showTvUi) { // if (Settings.showTvUi) {
//
val contextThemeWrapper = ContextThemeWrapper(activity, R.style.Theme_VLC) // your app theme here // val contextThemeWrapper = ContextThemeWrapper(activity, R.style.Theme_VLC_Black) // your app theme here
return inflater.cloneInContext(contextThemeWrapper).inflate(layout, container, true) // return inflater.cloneInContext(contextThemeWrapper).inflate(layout, container, true)
} // }
return inflater.inflate(layout, container, false) return inflater.inflate(layout, container, false)
} }
......
...@@ -45,8 +45,8 @@ class FoldersFragment : MediaBrowserFragment<FoldersViewModel>(), CtxActionRecei ...@@ -45,8 +45,8 @@ class FoldersFragment : MediaBrowserFragment<FoldersViewModel>(), CtxActionRecei
} }
} }
is FolderLongClick -> { is FolderLongClick -> {
adapter.multiSelectHelper.toggleSelection(action.position, true)
if (actionMode == null) { if (actionMode == null) {
adapter.multiSelectHelper.toggleSelection(action.position)
startActionMode() startActionMode()
} }
} }
......