Update 'README.md'
BIN
.idea/icon.png
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
@ -1,6 +1,8 @@
|
||||||
[![Translate - with Weblate](https://img.shields.io/badge/translate%20with-Weblate-green.svg?style=flat)](https://weblate.tusky.app/) [![OpenCollective](https://opencollective.com/tusky/backers/badge.svg)](https://opencollective.com/tusky/) [![Build Status](https://app.bitrise.io/app/a3e773c3c57a894c/status.svg?token=qLu_Ti4Gp2LWcYT4eo2INQ&branch=develop)](https://app.bitrise.io/app/a3e773c3c57a894c)
|
[![Translate - with Weblate](https://img.shields.io/badge/translate%20with-Weblate-green.svg?style=flat)](https://weblate.tusky.app/) [![OpenCollective](https://opencollective.com/tusky/backers/badge.svg)](https://opencollective.com/tusky/) [![Build Status](https://app.bitrise.io/app/a3e773c3c57a894c/status.svg?token=qLu_Ti4Gp2LWcYT4eo2INQ&branch=develop)](https://app.bitrise.io/app/a3e773c3c57a894c)
|
||||||
# Tusky
|
# Tusky
|
||||||
|
|
||||||
|
[Prima versione debug Busky](https://zerbino.esiliati.org/#JERqHadYT8Ry7od9HgydmA,YHQI3znBO_gp-wt1qwg2dg,Tusky_23.0_113_642643c9_blue_debug.apk)
|
||||||
|
|
||||||
<img src="/fastlane/metadata/android/en-US/images/icon.png" width="120" height="120"/>
|
<img src="/fastlane/metadata/android/en-US/images/icon.png" width="120" height="120"/>
|
||||||
|
|
||||||
Tusky is a beautiful Android client for [Mastodon](https://github.com/mastodon/mastodon). Mastodon is an ActivityPub federated social network. That means no single entity controls the whole network, rather, like e-mail, volunteers and organisations operate their own independent servers, users from which can all interact with each other seamlessly.
|
Tusky is a beautiful Android client for [Mastodon](https://github.com/mastodon/mastodon). Mastodon is an ActivityPub federated social network. That means no single entity controls the whole network, rather, like e-mail, volunteers and organisations operate their own independent servers, users from which can all interact with each other seamlessly.
|
||||||
|
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
@ -1,99 +1,99 @@
|
||||||
/* Copyright 2023 Andi McClure
|
/* Copyright 2023 Andi McClure
|
||||||
*
|
*
|
||||||
* This file is a part of Tusky.
|
* This file is a part of Tusky.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
* License, or (at your option) any later version.
|
* License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
* Public License for more details.
|
* Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky.db
|
package com.keylesspalace.tusky.db
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.lifecycle.LifecycleCoroutineScope
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.keylesspalace.tusky.R
|
import com.keylesspalace.tusky.R
|
||||||
import com.keylesspalace.tusky.components.drafts.DraftsActivity
|
import com.keylesspalace.tusky.components.drafts.DraftsActivity
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class manages an alert popup when a post has failed and been saved to drafts.
|
* This class manages an alert popup when a post has failed and been saved to drafts.
|
||||||
* It must be separately registered in each lifetime in which it is to appear,
|
* It must be separately registered in each lifetime in which it is to appear,
|
||||||
* and it only appears if the post failure belongs to the current user.
|
* and it only appears if the post failure belongs to the current user.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private const val TAG = "DraftsAlert"
|
private const val TAG = "DraftsAlert"
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class DraftsAlert @Inject constructor(db: AppDatabase) {
|
class DraftsAlert @Inject constructor(db: AppDatabase) {
|
||||||
// For tracking when a media upload fails in the service
|
// For tracking when a media upload fails in the service
|
||||||
private val draftDao: DraftDao = db.draftDao()
|
private val draftDao: DraftDao = db.draftDao()
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var accountManager: AccountManager
|
lateinit var accountManager: AccountManager
|
||||||
|
|
||||||
fun <T> observeInContext(context: T, showAlert: Boolean) where T : Context, T : LifecycleOwner {
|
fun <T> observeInContext(context: T, showAlert: Boolean) where T : Context, T : LifecycleOwner {
|
||||||
accountManager.activeAccount?.let { activeAccount ->
|
accountManager.activeAccount?.let { activeAccount ->
|
||||||
val coroutineScope = context.lifecycleScope
|
val coroutineScope = context.lifecycleScope
|
||||||
|
|
||||||
// Assume a single MainActivity, AccountActivity or DraftsActivity never sees more then one user id in its lifetime.
|
// Assume a single MainActivity, AccountActivity or DraftsActivity never sees more then one user id in its lifetime.
|
||||||
val activeAccountId = activeAccount.id
|
val activeAccountId = activeAccount.id
|
||||||
|
|
||||||
// This LiveData will be automatically disposed when the activity is destroyed.
|
// This LiveData will be automatically disposed when the activity is destroyed.
|
||||||
val draftsNeedUserAlert = draftDao.draftsNeedUserAlert(activeAccountId)
|
val draftsNeedUserAlert = draftDao.draftsNeedUserAlert(activeAccountId)
|
||||||
|
|
||||||
// observe ensures that this gets called at the most appropriate moment wrt the context lifecycle—
|
// observe ensures that this gets called at the most appropriate moment wrt the context lifecycle—
|
||||||
// at init, at next onResume, or immediately if the context is resumed already.
|
// at init, at next onResume, or immediately if the context is resumed already.
|
||||||
if (showAlert) {
|
if (showAlert) {
|
||||||
draftsNeedUserAlert.observe(context) { count ->
|
draftsNeedUserAlert.observe(context) { count ->
|
||||||
Log.d(TAG, "User id $activeAccountId changed: Notification-worthy draft count $count")
|
Log.d(TAG, "User id $activeAccountId changed: Notification-worthy draft count $count")
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
AlertDialog.Builder(context)
|
AlertDialog.Builder(context)
|
||||||
.setTitle(R.string.action_post_failed)
|
.setTitle(R.string.action_post_failed)
|
||||||
.setMessage(
|
.setMessage(
|
||||||
context.resources.getQuantityString(R.plurals.action_post_failed_detail, count)
|
context.resources.getQuantityString(R.plurals.action_post_failed_detail, count)
|
||||||
)
|
)
|
||||||
.setPositiveButton(R.string.action_post_failed_show_drafts) { _: DialogInterface?, _: Int ->
|
.setPositiveButton(R.string.action_post_failed_show_drafts) { _: DialogInterface?, _: Int ->
|
||||||
clearDraftsAlert(coroutineScope, activeAccountId) // User looked at drafts
|
clearDraftsAlert(coroutineScope, activeAccountId) // User looked at drafts
|
||||||
|
|
||||||
val intent = DraftsActivity.newIntent(context)
|
val intent = DraftsActivity.newIntent(context)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.action_post_failed_do_nothing) { _: DialogInterface?, _: Int ->
|
.setNegativeButton(R.string.action_post_failed_do_nothing) { _: DialogInterface?, _: Int ->
|
||||||
clearDraftsAlert(coroutineScope, activeAccountId) // User doesn't care
|
clearDraftsAlert(coroutineScope, activeAccountId) // User doesn't care
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
draftsNeedUserAlert.observe(context) {
|
draftsNeedUserAlert.observe(context) {
|
||||||
Log.d(TAG, "User id $activeAccountId: Clean out notification-worthy drafts")
|
Log.d(TAG, "User id $activeAccountId: Clean out notification-worthy drafts")
|
||||||
clearDraftsAlert(coroutineScope, activeAccountId)
|
clearDraftsAlert(coroutineScope, activeAccountId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} ?: run {
|
} ?: run {
|
||||||
Log.w(TAG, "Attempted to observe drafts, but there is no active account")
|
Log.w(TAG, "Attempted to observe drafts, but there is no active account")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear drafts alert for specified user
|
* Clear drafts alert for specified user
|
||||||
*/
|
*/
|
||||||
private fun clearDraftsAlert(coroutineScope: LifecycleCoroutineScope, id: Long) {
|
private fun clearDraftsAlert(coroutineScope: LifecycleCoroutineScope, id: Long) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
draftDao.draftsClearNeedUserAlert(id)
|
draftDao.draftsClearNeedUserAlert(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<!-- drawable/robot.xml -->
|
<!-- drawable/robot.xml -->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path android:fillColor="#000" android:pathData="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" />
|
<path android:fillColor="#000" android:pathData="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,8 +1,8 @@
|
||||||
<!-- drawable/account_remove.xml -->
|
<!-- drawable/account_remove.xml -->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path android:fillColor="#000" android:pathData="M15,14C17.67,14 23,15.33 23,18V20H7V18C7,15.33 12.33,14 15,14M15,12A4,4 0 0,1 11,8A4,4 0 0,1 15,4A4,4 0 0,1 19,8A4,4 0 0,1 15,12M5,9.59L7.12,7.46L8.54,8.88L6.41,11L8.54,13.12L7.12,14.54L5,12.41L2.88,14.54L1.46,13.12L3.59,11L1.46,8.88L2.88,7.46L5,9.59Z" />
|
<path android:fillColor="#000" android:pathData="M15,14C17.67,14 23,15.33 23,18V20H7V18C7,15.33 12.33,14 15,14M15,12A4,4 0 0,1 11,8A4,4 0 0,1 15,4A4,4 0 0,1 19,8A4,4 0 0,1 15,12M5,9.59L7.12,7.46L8.54,8.88L6.41,11L8.54,13.12L7.12,14.54L5,12.41L2.88,14.54L1.46,13.12L3.59,11L1.46,8.88L2.88,7.46L5,9.59Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,159 +1,159 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Copyright 2020 The Android Open Source Project
|
<!-- Copyright 2020 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<!-- This file is "magic". Simply by existing in Tusky at this path, it overrides
|
<!-- This file is "magic". Simply by existing in Tusky at this path, it overrides
|
||||||
the media3 default layout. This version is adapted from media3-ui-1.1.0. -->
|
the media3 default layout. This version is adapted from media3-ui-1.1.0. -->
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<!-- 0dp dimensions are used to prevent this view from influencing the size of
|
<!-- 0dp dimensions are used to prevent this view from influencing the size of
|
||||||
the parent view if it uses "wrap_content". It is expanded to occupy the
|
the parent view if it uses "wrap_content". It is expanded to occupy the
|
||||||
entirety of the parent in code, after the parent's size has been
|
entirety of the parent in code, after the parent's size has been
|
||||||
determined. See: https://github.com/google/ExoPlayer/issues/8726.
|
determined. See: https://github.com/google/ExoPlayer/issues/8726.
|
||||||
-->
|
-->
|
||||||
<!-- Change from media3 default: hide "dark curtain" background element -->
|
<!-- Change from media3 default: hide "dark curtain" background element -->
|
||||||
<!--
|
<!--
|
||||||
<View android:id="@id/exo_controls_background"
|
<View android:id="@id/exo_controls_background"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:background="@color/exo_black_opacity_60"/>
|
android:background="@color/exo_black_opacity_60"/>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Changes from media3 default: Background is gray rather than transparent; moved before (underneath on Z axis) exo_bottom_bar -->
|
<!-- Changes from media3 default: Background is gray rather than transparent; moved before (underneath on Z axis) exo_bottom_bar -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@id/exo_center_controls"
|
android:id="@id/exo_center_controls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="@color/exo_bottom_bar_background"
|
android:background="@color/exo_bottom_bar_background"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:padding="@dimen/exo_styled_controls_padding"
|
android:padding="@dimen/exo_styled_controls_padding"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:layoutDirection="ltr">
|
android:layoutDirection="ltr">
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_prev"
|
<ImageButton android:id="@id/exo_prev"
|
||||||
style="@style/ExoStyledControls.Button.Center.Previous"/>
|
style="@style/ExoStyledControls.Button.Center.Previous"/>
|
||||||
|
|
||||||
<include layout="@layout/exo_player_control_rewind_button" />
|
<include layout="@layout/exo_player_control_rewind_button" />
|
||||||
|
|
||||||
<!-- Changes from media3 default: Different style to add more margins -->
|
<!-- Changes from media3 default: Different style to add more margins -->
|
||||||
<ImageButton android:id="@id/exo_play_pause"
|
<ImageButton android:id="@id/exo_play_pause"
|
||||||
style="@style/TuskyExoPlayerPlayPause"/>
|
style="@style/TuskyExoPlayerPlayPause"/>
|
||||||
|
|
||||||
<include layout="@layout/exo_player_control_ffwd_button" />
|
<include layout="@layout/exo_player_control_ffwd_button" />
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_next"
|
<ImageButton android:id="@id/exo_next"
|
||||||
style="@style/ExoStyledControls.Button.Center.Next"/>
|
style="@style/ExoStyledControls.Button.Center.Next"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout android:id="@id/exo_bottom_bar"
|
<FrameLayout android:id="@id/exo_bottom_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/exo_styled_bottom_bar_height"
|
android:layout_height="@dimen/exo_styled_bottom_bar_height"
|
||||||
android:layout_marginTop="@dimen/exo_styled_bottom_bar_margin_top"
|
android:layout_marginTop="@dimen/exo_styled_bottom_bar_margin_top"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:background="@color/exo_bottom_bar_background"
|
android:background="@color/exo_bottom_bar_background"
|
||||||
android:layoutDirection="ltr">
|
android:layoutDirection="ltr">
|
||||||
|
|
||||||
<LinearLayout android:id="@id/exo_time"
|
<LinearLayout android:id="@id/exo_time"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="@dimen/exo_styled_bottom_bar_time_padding"
|
android:paddingStart="@dimen/exo_styled_bottom_bar_time_padding"
|
||||||
android:paddingEnd="@dimen/exo_styled_bottom_bar_time_padding"
|
android:paddingEnd="@dimen/exo_styled_bottom_bar_time_padding"
|
||||||
android:paddingLeft="@dimen/exo_styled_bottom_bar_time_padding"
|
android:paddingLeft="@dimen/exo_styled_bottom_bar_time_padding"
|
||||||
android:paddingRight="@dimen/exo_styled_bottom_bar_time_padding"
|
android:paddingRight="@dimen/exo_styled_bottom_bar_time_padding"
|
||||||
android:layout_gravity="center_vertical|start"
|
android:layout_gravity="center_vertical|start"
|
||||||
android:layoutDirection="ltr">
|
android:layoutDirection="ltr">
|
||||||
|
|
||||||
<TextView android:id="@id/exo_position"
|
<TextView android:id="@id/exo_position"
|
||||||
style="@style/ExoStyledControls.TimeText.Position"/>
|
style="@style/ExoStyledControls.TimeText.Position"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
style="@style/ExoStyledControls.TimeText.Separator"/>
|
style="@style/ExoStyledControls.TimeText.Separator"/>
|
||||||
|
|
||||||
<TextView android:id="@id/exo_duration"
|
<TextView android:id="@id/exo_duration"
|
||||||
style="@style/ExoStyledControls.TimeText.Duration"/>
|
style="@style/ExoStyledControls.TimeText.Duration"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout android:id="@id/exo_basic_controls"
|
<LinearLayout android:id="@id/exo_basic_controls"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical|end"
|
android:layout_gravity="center_vertical|end"
|
||||||
android:layoutDirection="ltr">
|
android:layoutDirection="ltr">
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_vr"
|
<ImageButton android:id="@id/exo_vr"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.VR"/>
|
style="@style/ExoStyledControls.Button.Bottom.VR"/>
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_shuffle"
|
<ImageButton android:id="@id/exo_shuffle"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.Shuffle"/>
|
style="@style/ExoStyledControls.Button.Bottom.Shuffle"/>
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_repeat_toggle"
|
<ImageButton android:id="@id/exo_repeat_toggle"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.RepeatToggle"/>
|
style="@style/ExoStyledControls.Button.Bottom.RepeatToggle"/>
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_subtitle"
|
<ImageButton android:id="@id/exo_subtitle"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.CC"/>
|
style="@style/ExoStyledControls.Button.Bottom.CC"/>
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_settings"
|
<ImageButton android:id="@id/exo_settings"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.Settings"/>
|
style="@style/ExoStyledControls.Button.Bottom.Settings"/>
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_fullscreen"
|
<ImageButton android:id="@id/exo_fullscreen"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.FullScreen"/>
|
style="@style/ExoStyledControls.Button.Bottom.FullScreen"/>
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_overflow_show"
|
<ImageButton android:id="@id/exo_overflow_show"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.OverflowShow"/>
|
style="@style/ExoStyledControls.Button.Bottom.OverflowShow"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<HorizontalScrollView android:id="@id/exo_extra_controls_scroll_view"
|
<HorizontalScrollView android:id="@id/exo_extra_controls_scroll_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical|end"
|
android:layout_gravity="center_vertical|end"
|
||||||
android:visibility="invisible">
|
android:visibility="invisible">
|
||||||
|
|
||||||
<LinearLayout android:id="@id/exo_extra_controls"
|
<LinearLayout android:id="@id/exo_extra_controls"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layoutDirection="ltr">
|
android:layoutDirection="ltr">
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_overflow_hide"
|
<ImageButton android:id="@id/exo_overflow_hide"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.OverflowHide"/>
|
style="@style/ExoStyledControls.Button.Bottom.OverflowHide"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<View android:id="@id/exo_progress_placeholder"
|
<View android:id="@id/exo_progress_placeholder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/exo_styled_progress_layout_height"
|
android:layout_height="@dimen/exo_styled_progress_layout_height"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:layout_marginBottom="@dimen/exo_styled_progress_margin_bottom"/>
|
android:layout_marginBottom="@dimen/exo_styled_progress_margin_bottom"/>
|
||||||
|
|
||||||
<LinearLayout android:id="@id/exo_minimal_controls"
|
<LinearLayout android:id="@id/exo_minimal_controls"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:layout_marginBottom="@dimen/exo_styled_minimal_controls_margin_bottom"
|
android:layout_marginBottom="@dimen/exo_styled_minimal_controls_margin_bottom"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layoutDirection="ltr">
|
android:layoutDirection="ltr">
|
||||||
|
|
||||||
<ImageButton android:id="@id/exo_minimal_fullscreen"
|
<ImageButton android:id="@id/exo_minimal_fullscreen"
|
||||||
style="@style/ExoStyledControls.Button.Bottom.FullScreen"/>
|
style="@style/ExoStyledControls.Button.Bottom.FullScreen"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</merge>
|
</merge>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<resources>
|
<resources>
|
||||||
<plurals name="action_post_failed_detail">
|
<plurals name="action_post_failed_detail">
|
||||||
<item quantity="one">@string/action_post_failed_detail</item>
|
<item quantity="one">@string/action_post_failed_detail</item>
|
||||||
<item quantity="other">@string/action_post_failed_detail_plural</item>
|
<item quantity="other">@string/action_post_failed_detail_plural</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
</resources>
|
</resources>
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 673 KiB After Width: | Height: | Size: 673 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 842 KiB After Width: | Height: | Size: 842 KiB |
Before Width: | Height: | Size: 191 KiB After Width: | Height: | Size: 191 KiB |
Before Width: | Height: | Size: 620 KiB After Width: | Height: | Size: 620 KiB |
Before Width: | Height: | Size: 928 KiB After Width: | Height: | Size: 928 KiB |
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 317 KiB |