Browse Source

Improve the widget seek buttons

Add a widget setting to hide the seek buttons
Improve the control bar layout
Small widgets util refactor
merge-requests/1492/head
Nicolas Pomepuy 4 years ago
committed by Duncan McNamara
parent
commit
3a2445578d
  1. 4
      application/mediadb/src/main/java/org/videolan/vlc/database/MediaDatabase.kt
  2. 6
      application/mediadb/src/main/java/org/videolan/vlc/database/Migrations.kt
  3. 4
      application/mediadb/src/main/java/org/videolan/vlc/mediadb/models/Widget.kt
  4. 1
      application/resources/src/main/res/values/strings.xml
  5. 11
      application/vlc-android/res/layout/widget_content_full_player.xml
  6. 7
      application/vlc-android/res/xml/preferences_widgets.xml
  7. 19
      application/vlc-android/src/org/videolan/vlc/gui/preferences/widgets/PreferencesWidgets.kt
  8. 2
      application/vlc-android/src/org/videolan/vlc/repository/WidgetRepository.kt
  9. 42
      application/vlc-android/src/org/videolan/vlc/widget/MiniPlayerAppWidgetProvider.kt
  10. 38
      application/vlc-android/src/org/videolan/vlc/widget/utils/WidgetUtils.kt

4
application/mediadb/src/main/java/org/videolan/vlc/database/MediaDatabase.kt

@ -33,7 +33,7 @@ import org.videolan.vlc.mediadb.models.*
private const val DB_NAME = "vlc_database"
@Database(entities = [ExternalSub::class, Slave::class, BrowserFav::class, CustomDirectory::class, Widget::class], version = 31, exportSchema = false)
@Database(entities = [ExternalSub::class, Slave::class, BrowserFav::class, CustomDirectory::class, Widget::class], version = 32, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MediaDatabase: RoomDatabase() {
abstract fun externalSubDao(): ExternalSubDao
@ -54,7 +54,7 @@ private fun buildDatabase(context: Context) = Room.databaseBuilder(context.appli
migration_17_18, migration_18_19, migration_19_20, migration_20_21,
migration_21_22, migration_22_23, migration_23_24, migration_24_25,
migration_25_26, migration_26_27, migration_27_28, migration_28_29,
migration_29_30, migration_30_31)
migration_29_30, migration_30_31, migration_31_32)
.addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) { if (!AndroidDevices.isTv) populateDB(context) }
})

6
application/mediadb/src/main/java/org/videolan/vlc/database/Migrations.kt

@ -218,6 +218,12 @@ val migration_30_31 = object:Migration(30, 31) {
}
}
val migration_31_32 = object:Migration(31, 32) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE $WIDGET_TABLE_NAME ADD COLUMN show_seek INTEGER NOT NULL DEFAULT 0;")
}
}
@OptIn(DelicateCoroutinesApi::class)
fun populateDB(context: Context) = GlobalScope.launch(Dispatchers.IO) {
val uris = listOf(AndroidDevices.MediaFolders.EXTERNAL_PUBLIC_MOVIES_DIRECTORY_URI,

4
application/mediadb/src/main/java/org/videolan/vlc/mediadb/models/Widget.kt

@ -52,5 +52,7 @@ data class Widget(
@ColumnInfo(name = "opacity")
var opacity: Int,
@ColumnInfo(name = "show_configure")
var showConfigure: Boolean
var showConfigure: Boolean,
@ColumnInfo(name = "show_seek")
var showSeek: Boolean
)

1
application/resources/src/main/res/values/strings.xml

@ -971,6 +971,7 @@
<string name="configure_widget">Widget configuration</string>
<string name="widget_preview">Widget preview</string>
<string name="widget_forward_delay">Forward time delay</string>
<string name="widget_show_seek">Show seek buttons</string>
<string name="widget_rewind_delay">Backward time delay</string>
<string name="widget_show_configure">Show configuration icon</string>
<string name="widget_show_configure_summary">Even if it\'s not shown, you can tap the upper right corner to open the configuration</string>

11
application/vlc-android/res/layout/widget_content_full_player.xml

@ -35,6 +35,12 @@
android:gravity="center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="1dp"
android:id="@+id/widget_left_space"
android:layout_weight="1" />
<ImageButton
android:id="@+id/backward"
android:layout_width="wrap_content"
@ -140,6 +146,11 @@
android:clickable="true"
android:scaleType="centerInside"
tools:src="@drawable/ic_widget_next_normal" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="1dp"
android:id="@+id/widget_right_space"
android:layout_weight="1" />
</LinearLayout>

7
application/vlc-android/res/xml/preferences_widgets.xml

@ -60,14 +60,21 @@
app:cpv_showAlphaSlider="false"
android:title="@string/widget_foreground"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="widget_show_seek"
android:title="@string/widget_show_seek" />
<org.videolan.vlc.gui.view.NumberPickerPreference
android:defaultValue="10"
app:key="widget_forward_delay"
android:dependency="widget_show_seek"
app:title="@string/widget_forward_delay" />
<org.videolan.vlc.gui.view.NumberPickerPreference
android:defaultValue="10"
app:key="widget_rewind_delay"
android:dependency="widget_show_seek"
app:title="@string/widget_rewind_delay" />
<CheckBoxPreference

19
application/vlc-android/src/org/videolan/vlc/gui/preferences/widgets/PreferencesWidgets.kt

@ -46,8 +46,12 @@ import org.videolan.tools.WIDGETS_FOREGROUND_LAST_COLORS
import org.videolan.tools.putSingle
import org.videolan.vlc.R
import org.videolan.vlc.gui.preferences.BasePreferenceFragment
import org.videolan.vlc.gui.view.NumberPickerPreference
import org.videolan.vlc.repository.WidgetRepository
import org.videolan.vlc.widget.WidgetViewModel
import org.videolan.vlc.widget.utils.WidgetType
import org.videolan.vlc.widget.utils.WidgetUtils.getWidgetTypeFromSize
import org.videolan.vlc.widget.utils.WidgetUtils.hasEnoughSpaceForSeek
const val WIDGET_ID = "WIDGET_ID"
@ -59,6 +63,9 @@ class PreferencesWidgets : BasePreferenceFragment(), SharedPreferences.OnSharedP
private lateinit var backgroundPreference: ColorPreferenceCompat
private lateinit var foregroundPreference: ColorPreferenceCompat
private lateinit var lightThemePreference: CheckBoxPreference
private lateinit var showSeek: CheckBoxPreference
private lateinit var forwardDelay: NumberPickerPreference
private lateinit var rewindDelay: NumberPickerPreference
override fun getXml() = R.xml.preferences_widgets
@ -86,6 +93,9 @@ class PreferencesWidgets : BasePreferenceFragment(), SharedPreferences.OnSharedP
backgroundPreference = findPreference("background_color")!!
foregroundPreference = findPreference("foreground_color")!!
lightThemePreference = findPreference("widget_light_theme")!!
showSeek = findPreference("widget_show_seek")!!
forwardDelay = findPreference("widget_forward_delay")!!
rewindDelay = findPreference("widget_rewind_delay")!!
val configurationIcon = findPreference<CheckBoxPreference>("widget_show_configure")!!
val themePreference = findPreference<ListPreference>("widget_theme")!!
@ -109,6 +119,11 @@ class PreferencesWidgets : BasePreferenceFragment(), SharedPreferences.OnSharedP
lightThemePreference.isChecked = widget.lightTheme
lightThemePreference.isVisible = widget.theme != 2
configurationIcon.isChecked = widget.showConfigure
val widgetType = getWidgetTypeFromSize(widget.width, widget.height)
val showSeekPrefs = (widgetType == WidgetType.MINI || widgetType == WidgetType.MACRO) && hasEnoughSpaceForSeek(widget, widgetType)
showSeek.isVisible = showSeekPrefs
forwardDelay.isVisible = showSeekPrefs
rewindDelay.isVisible = showSeekPrefs
}
if (!DynamicColors.isDynamicColorAvailable()) {
@ -162,6 +177,10 @@ class PreferencesWidgets : BasePreferenceFragment(), SharedPreferences.OnSharedP
model.widget.value?.showConfigure = newValue
}
"widget_show_seek" -> {
val newValue = sharedPreferences.getBoolean(key, true)
model.widget.value?.showSeek = newValue
}
}
updateWidgetEntity()
}

2
application/vlc-android/src/org/videolan/vlc/repository/WidgetRepository.kt

@ -67,7 +67,7 @@ class WidgetRepository(private val widgetDao: WidgetDao) {
}
suspend fun createNew(context: Context, appWidgetId: Int): Widget {
val widget = Widget(appWidgetId, 0, 0, 0, true, ContextCompat.getColor(context, R.color.black), ContextCompat.getColor(context, R.color.white), 10, 10, 100, true)
val widget = Widget(appWidgetId, 0, 0, 0, true, ContextCompat.getColor(context, R.color.black), ContextCompat.getColor(context, R.color.white), 10, 10, 100, true, true)
addWidget(widget)
return widget
}

42
application/vlc-android/src/org/videolan/vlc/widget/MiniPlayerAppWidgetProvider.kt

@ -59,6 +59,8 @@ import org.videolan.vlc.repository.WidgetRepository
import org.videolan.vlc.util.TextUtils
import org.videolan.vlc.util.getPendingIntent
import org.videolan.vlc.widget.utils.*
import org.videolan.vlc.widget.utils.WidgetUtils.getWidgetTypeFromSize
import org.videolan.vlc.widget.utils.WidgetUtils.shouldShowSeek
import java.util.*
@ -353,14 +355,17 @@ class MiniPlayerAppWidgetProvider : AppWidgetProvider() {
}
}
log(appWidgetId, WidgetLogType.INFO, "hasEnoughSpaceForSeek: ${hasEnoughSpaceForSeek(widgetCacheEntry, widgetType)}")
val showSeek = shouldShowSeek(widgetCacheEntry.widget, widgetType)
log(appWidgetId, WidgetLogType.INFO, "hasEnoughSpaceForSeek: $showSeek")
views.setViewVisibility(R.id.progress_round, if (playing) View.VISIBLE else View.GONE)
views.setViewVisibility(R.id.forward, if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.backward, if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_forward, if (!hasEnoughSpaceForSeek(widgetCacheEntry, widgetType)) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_forward_text, if (!hasEnoughSpaceForSeek(widgetCacheEntry, widgetType)) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_rewind, if (!hasEnoughSpaceForSeek(widgetCacheEntry, widgetType)) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_rewind_text, if (!hasEnoughSpaceForSeek(widgetCacheEntry, widgetType)) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_forward, if (!showSeek) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_forward_text, if (!showSeek) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_rewind, if (!showSeek) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.seek_rewind_text, if (!showSeek) View.GONE else if (playing) View.VISIBLE else View.INVISIBLE)
views.setViewVisibility(R.id.widget_left_space, if (!showSeek) View.VISIBLE else if (playing) View.GONE else View.VISIBLE)
views.setViewVisibility(R.id.widget_right_space, if (!showSeek) View.VISIBLE else if (playing) View.GONE else View.VISIBLE)
views.setContentDescription(R.id.seek_rewind, context.getString(R.string.seek_backward_content_description, widgetCacheEntry.widget.rewindDelay.toString()))
views.setContentDescription(R.id.seek_forward, context.getString(R.string.seek_forward_content_description, widgetCacheEntry.widget.forwardDelay.toString()))
@ -389,33 +394,6 @@ class MiniPlayerAppWidgetProvider : AppWidgetProvider() {
return views
}
/**
* Calculate the [WidgetType] depending on the size
*
* @param width the widget width
* @param height the widget height
* @return the [WidgetType] for this size
*/
private fun getWidgetTypeFromSize(width: Int, height: Int) = when {
width > 220 && height > 220 -> WidgetType.MACRO
width > 220 && height > 72 -> WidgetType.MINI
width > 128 && height > 148 -> WidgetType.MICRO
else -> WidgetType.PILL
}
/**
* Check if the widget has enough space to display the seek icons
*
* @param widgetCacheEntry the widget cache entry to check the size on
* @param widgetType the current [WidgetType]
* @return true if the widget has nough space
*/
private fun hasEnoughSpaceForSeek(widgetCacheEntry: WidgetCacheEntry, widgetType: WidgetType) = when (widgetType) {
WidgetType.MINI -> widgetCacheEntry.widget.width.dp > widgetCacheEntry.widget.height.dp + 48.dp * 5
WidgetType.MACRO -> widgetCacheEntry.widget.width.dp > 48.dp * 5
else -> false
}
/**
* Cuts the cover bitmap depending on the [WidgetType]
*

38
application/vlc-android/src/org/videolan/vlc/widget/utils/WidgetUtils.kt

@ -274,4 +274,42 @@ fun WidgetCacheEntry.generatePillProgressbar(context: Context, progress: Float):
enum class WidgetType(@LayoutRes val layout: Int) {
PILL(R.layout.widget_pill), MINI(R.layout.widget_mini), MICRO(R.layout.widget_micro), MACRO(R.layout.widget_macro)
}
object WidgetUtils {
/**
* Calculate the [WidgetType] depending on the size
*
* @param width the widget width
* @param height the widget height
* @return the [WidgetType] for this size
*/
fun getWidgetTypeFromSize(width: Int, height: Int) = when {
width > 220 && height > 220 -> WidgetType.MACRO
width > 220 && height > 72 -> WidgetType.MINI
width > 128 && height > 148 -> WidgetType.MICRO
else -> WidgetType.PILL
}
/**
* Check if the widget has enough space to display the seek icons
*
* @param widget the widget to check the size on
* @param widgetType the current [WidgetType]
* @return true if the widget has enough space
*/
fun hasEnoughSpaceForSeek(widget: Widget, widgetType: WidgetType) = when (widgetType) {
WidgetType.MINI -> widget.width.dp > widget.height.dp + 48.dp * 5
WidgetType.MACRO -> widget.width.dp > 48.dp * 5
else -> false
}
/**
* Check if the widget should show the seek buttons
*
* @param widget the widget to check the size on
* @param widgetType the current [WidgetType]
* @return true if the widget has enough space and the setting is set to on
*/
fun shouldShowSeek(widget: Widget, widgetType: WidgetType) = widget.showSeek && hasEnoughSpaceForSeek(widget, widgetType)
}
Loading…
Cancel
Save