Update license
This commit is contained in:
parent
0f22127a12
commit
211db34142
2 changed files with 365 additions and 176 deletions
184
AUTHORS
Normal file
184
AUTHORS
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
# List of authors of Husky
|
||||||
|
|
||||||
|
Current maintainer: Adolfo Santiago (captainepoch)
|
||||||
|
|
||||||
|
# All of the contributors to Tusky and Husky
|
||||||
|
#
|
||||||
|
# This list was retrived from the original Husky repository. If someone is
|
||||||
|
# missing or you want to add or change something, send an email to the
|
||||||
|
# project's mailist.
|
||||||
|
Aditoo
|
||||||
|
Aditoo17
|
||||||
|
Akarshan Biswas
|
||||||
|
Alibek Omarov (a1batross)
|
||||||
|
Alice Heart
|
||||||
|
Allysson Samuel Amorim Vaz Cunha
|
||||||
|
Alperen
|
||||||
|
Anna e só
|
||||||
|
Anonymous
|
||||||
|
Artur Mancha
|
||||||
|
BOSCH, Cedric
|
||||||
|
Balasankar C
|
||||||
|
Basix
|
||||||
|
Ben
|
||||||
|
Bernd
|
||||||
|
Billy Brawner
|
||||||
|
Boced66
|
||||||
|
Briar Rose Schreiber
|
||||||
|
ButterflyOfFire
|
||||||
|
Caleb Maclennan
|
||||||
|
Christian Paul
|
||||||
|
Conny Duck
|
||||||
|
Connyduck
|
||||||
|
Conor Flynn
|
||||||
|
Constantin A
|
||||||
|
Criss
|
||||||
|
CryptKiddie
|
||||||
|
Dani
|
||||||
|
Danial Behzadi
|
||||||
|
Daniele Lira Mereb
|
||||||
|
David Teresi
|
||||||
|
Dryusdan
|
||||||
|
Elarcis
|
||||||
|
Elias Mårtenson
|
||||||
|
Eugen
|
||||||
|
Eugen Rochko
|
||||||
|
Evgeny
|
||||||
|
Evgeny Petrov
|
||||||
|
FeiYang
|
||||||
|
FlameArche
|
||||||
|
Francesc Galí
|
||||||
|
Frieder Bluemle
|
||||||
|
Gareth Murphy
|
||||||
|
Garrit Franke
|
||||||
|
Gian Sass
|
||||||
|
Gyuhwan Park
|
||||||
|
Hararan
|
||||||
|
HellPie
|
||||||
|
Henri Gourvest
|
||||||
|
INAGAKI Hiroshi
|
||||||
|
Isak Alexander
|
||||||
|
Isak Holmström
|
||||||
|
Ivan Kupalov
|
||||||
|
Jan Boddez
|
||||||
|
Jeong Arm
|
||||||
|
Jeroen
|
||||||
|
Joan Montané
|
||||||
|
Johannes Barre
|
||||||
|
Juanjo Salvador
|
||||||
|
Karol Kosek
|
||||||
|
Kazuki KANDA
|
||||||
|
Konrad Pozniak
|
||||||
|
Koyu Berteon
|
||||||
|
Kristijan Tkalec
|
||||||
|
Krzysztof Jurewicz
|
||||||
|
Kyle Sunden
|
||||||
|
Kévin Commaille
|
||||||
|
Len Chan
|
||||||
|
Levi Bard
|
||||||
|
Manimaran.K
|
||||||
|
Marcin Mikołajczak
|
||||||
|
Marie Axelsson
|
||||||
|
Markel @wakutiteo
|
||||||
|
Mary
|
||||||
|
Michel
|
||||||
|
Mickson
|
||||||
|
Mihai Boisteanu
|
||||||
|
Mike Barnes
|
||||||
|
Mitchell Hentges
|
||||||
|
Mostafa Ahangarha
|
||||||
|
Muha Aliss
|
||||||
|
MzA
|
||||||
|
Mélanie Chauvel
|
||||||
|
Mélanie Chauvel (ariasuni)
|
||||||
|
Neville Park
|
||||||
|
Nicholas Tinsley
|
||||||
|
Noah Akers
|
||||||
|
Ondřej Hruška
|
||||||
|
Pangoraw
|
||||||
|
Paul
|
||||||
|
Pellaeon Lin
|
||||||
|
Peter Cai
|
||||||
|
PhotonQyv
|
||||||
|
Poulpette
|
||||||
|
Prat
|
||||||
|
Quentí
|
||||||
|
Quim Gil
|
||||||
|
Raphael Michel
|
||||||
|
Repu
|
||||||
|
Ryu jongheon
|
||||||
|
Sandor Teglasy
|
||||||
|
Selyan Slimane Amiri
|
||||||
|
Serage(pl)
|
||||||
|
Sergio López
|
||||||
|
Serkan Cık
|
||||||
|
Sojo
|
||||||
|
Subin Siby
|
||||||
|
Sveinn í Felli
|
||||||
|
Sylke Vicious
|
||||||
|
Sylvia van Os
|
||||||
|
Thomas Citharel
|
||||||
|
Tibike Miklós
|
||||||
|
Tryton Van Meer
|
||||||
|
Unai Tolosa Pontesta
|
||||||
|
Vavassor
|
||||||
|
Vegard Skjefstad
|
||||||
|
Vignesh Kumar
|
||||||
|
Vivianne
|
||||||
|
Weblate
|
||||||
|
Wesley Ellis
|
||||||
|
Yaroslav
|
||||||
|
Zachary Epps
|
||||||
|
Zoltán Gera
|
||||||
|
aka-rin
|
||||||
|
ati3
|
||||||
|
autumnontape
|
||||||
|
charlag
|
||||||
|
dadosch
|
||||||
|
dani
|
||||||
|
daycode
|
||||||
|
dimqua
|
||||||
|
duggalsu
|
||||||
|
eleete0712
|
||||||
|
flyingrub
|
||||||
|
freetux
|
||||||
|
goofy-bz
|
||||||
|
hg
|
||||||
|
in_dow
|
||||||
|
jchmrt
|
||||||
|
jeroenpraat
|
||||||
|
jma
|
||||||
|
knuxify
|
||||||
|
koyu
|
||||||
|
kyori
|
||||||
|
kyori19
|
||||||
|
lenchan139
|
||||||
|
lindwurm
|
||||||
|
littlebelgianwriter
|
||||||
|
m4sk1n
|
||||||
|
marcin mikołajczak
|
||||||
|
mewmew
|
||||||
|
mike castleman
|
||||||
|
mr.bumper Gonzalez perez
|
||||||
|
mynameismonkey
|
||||||
|
nailyk
|
||||||
|
nailyk-fr
|
||||||
|
nailyk-weblate
|
||||||
|
nora
|
||||||
|
nore715
|
||||||
|
ntngrtltr
|
||||||
|
orimpe
|
||||||
|
pandasoft0
|
||||||
|
qwazix
|
||||||
|
remi6397
|
||||||
|
serage.betelmal
|
||||||
|
simevo
|
||||||
|
tolstoevsky
|
||||||
|
torrentcome
|
||||||
|
toumi
|
||||||
|
tsdgeos
|
||||||
|
uckfayer
|
||||||
|
vala
|
||||||
|
zital
|
||||||
|
Óliver García Albertos
|
||||||
|
Хлеп
|
|
@ -1,17 +1,22 @@
|
||||||
/* Copyright 2017 Andrew Dawson
|
/*
|
||||||
|
* Husky -- A Pleroma client for Android
|
||||||
*
|
*
|
||||||
* This file is a part of Tusky.
|
* Copyright (C) 2021 The Husky Developers
|
||||||
|
* Copyright (C) 2017 Andrew Dawson
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
* it under the terms of the GNU General Public License as published by
|
||||||
* License, or (at your option) any later version.
|
* the Free Software Foundation, either version 3 of the 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
|
* This program is distributed in the hope that it will be useful,
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* Public License for more details.
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General 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
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.keylesspalace.tusky.fragment
|
package com.keylesspalace.tusky.fragment
|
||||||
|
|
||||||
|
@ -44,202 +49,202 @@ import timber.log.Timber
|
||||||
|
|
||||||
class ViewVideoFragment : ViewMediaFragment() {
|
class ViewVideoFragment : ViewMediaFragment() {
|
||||||
|
|
||||||
private lateinit var toolbar: View
|
private lateinit var toolbar: View
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
private val hideToolbar = Runnable {
|
private val hideToolbar = Runnable {
|
||||||
// Hoist toolbar hiding to activity so it can track state across different fragments
|
// Hoist toolbar hiding to activity so it can track state across different fragments
|
||||||
// This is explicitly stored as runnable so that we pass it to the handler later for cancellation
|
// This is explicitly stored as runnable so that we pass it to the handler later for cancellation
|
||||||
mediaActivity.onPhotoTap()
|
mediaActivity.onPhotoTap()
|
||||||
mediaController.hide()
|
mediaController.hide()
|
||||||
}
|
}
|
||||||
private lateinit var mediaActivity: ViewMediaActivity
|
private lateinit var mediaActivity: ViewMediaActivity
|
||||||
private val TOOLBAR_HIDE_DELAY_MS = 3000L
|
private val TOOLBAR_HIDE_DELAY_MS = 3000L
|
||||||
private lateinit var mediaController: MediaController
|
private lateinit var mediaController: MediaController
|
||||||
private var isAudio = false
|
private var isAudio = false
|
||||||
|
|
||||||
private var exoPlayer: SimpleExoPlayer? = null
|
private var exoPlayer: SimpleExoPlayer? = null
|
||||||
private val playbackStateListener: Player.Listener = playbackStateListener()
|
private val playbackStateListener: Player.Listener = playbackStateListener()
|
||||||
private var playWhenReady = true
|
private var playWhenReady = true
|
||||||
private var currentWindow = 0
|
private var currentWindow = 0
|
||||||
private var playbackPosition = 0L
|
private var playbackPosition = 0L
|
||||||
|
|
||||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||||
// Start/pause/resume video playback as fragment is shown/hidden
|
// Start/pause/resume video playback as fragment is shown/hidden
|
||||||
super.setUserVisibleHint(isVisibleToUser)
|
super.setUserVisibleHint(isVisibleToUser)
|
||||||
|
|
||||||
if(videoView == null) {
|
if(videoView == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isVisibleToUser) {
|
if(isVisibleToUser) {
|
||||||
if(mediaActivity.isToolbarVisible) {
|
if(mediaActivity.isToolbarVisible) {
|
||||||
handler.postDelayed(hideToolbar, TOOLBAR_HIDE_DELAY_MS)
|
handler.postDelayed(hideToolbar, TOOLBAR_HIDE_DELAY_MS)
|
||||||
}
|
}
|
||||||
exoPlayer?.play()
|
exoPlayer?.play()
|
||||||
} else {
|
} else {
|
||||||
handler.removeCallbacks(hideToolbar)
|
handler.removeCallbacks(hideToolbar)
|
||||||
exoPlayer?.pause()
|
exoPlayer?.pause()
|
||||||
mediaController.hide()
|
mediaController.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun setupMediaView(
|
override fun setupMediaView(
|
||||||
url: String,
|
url: String,
|
||||||
previewUrl: String?,
|
previewUrl: String?,
|
||||||
description: String?,
|
description: String?,
|
||||||
showingDescription: Boolean
|
showingDescription: Boolean
|
||||||
) {
|
) {
|
||||||
mediaDescription.text = description
|
mediaDescription.text = description
|
||||||
mediaDescription.visible(showingDescription)
|
mediaDescription.visible(showingDescription)
|
||||||
|
|
||||||
videoView.transitionName = url
|
videoView.transitionName = url
|
||||||
mediaController = object : MediaController(mediaActivity) {
|
mediaController = object : MediaController(mediaActivity) {
|
||||||
override fun show(timeout: Int) {
|
override fun show(timeout: Int) {
|
||||||
// We're doing manual auto-close management.
|
// We're doing manual auto-close management.
|
||||||
// Also, take focus back from the pause button so we can use the back button.
|
// Also, take focus back from the pause button so we can use the back button.
|
||||||
super.show(0)
|
super.show(0)
|
||||||
mediaController.requestFocus()
|
mediaController.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
||||||
if(event?.keyCode == KeyEvent.KEYCODE_BACK) {
|
if(event?.keyCode == KeyEvent.KEYCODE_BACK) {
|
||||||
if(event.action == KeyEvent.ACTION_UP) {
|
if(event.action == KeyEvent.ACTION_UP) {
|
||||||
hide()
|
hide()
|
||||||
activity?.supportFinishAfterTransition()
|
activity?.supportFinishAfterTransition()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val trackSelector = DefaultTrackSelector(requireActivity()).apply {
|
val trackSelector = DefaultTrackSelector(requireActivity()).apply {
|
||||||
setParameters(buildUponParameters().setMaxVideoSizeSd())
|
setParameters(buildUponParameters().setMaxVideoSizeSd())
|
||||||
}
|
}
|
||||||
|
|
||||||
exoPlayer = SimpleExoPlayer.Builder(requireActivity())
|
exoPlayer = SimpleExoPlayer.Builder(requireActivity())
|
||||||
.setTrackSelector(trackSelector)
|
.setTrackSelector(trackSelector)
|
||||||
.build()
|
.build()
|
||||||
.also { player ->
|
.also { player ->
|
||||||
videoView.player = player
|
videoView.player = player
|
||||||
|
|
||||||
val mediaItem = MediaItem.Builder()
|
val mediaItem = MediaItem.Builder()
|
||||||
.setUri(Uri.parse(url))
|
.setUri(Uri.parse(url))
|
||||||
.build()
|
.build()
|
||||||
player.setMediaItem(mediaItem)
|
player.setMediaItem(mediaItem)
|
||||||
|
|
||||||
player.addListener(playbackStateListener)
|
player.addListener(playbackStateListener)
|
||||||
player.seekTo(currentWindow, playbackPosition)
|
player.seekTo(currentWindow, playbackPosition)
|
||||||
player.playWhenReady = playWhenReady
|
player.playWhenReady = playWhenReady
|
||||||
|
|
||||||
player.prepare()
|
player.prepare()
|
||||||
}
|
}
|
||||||
|
|
||||||
videoView.requestFocus()
|
videoView.requestFocus()
|
||||||
|
|
||||||
if(arguments!!.getBoolean(ARG_START_POSTPONED_TRANSITION)) {
|
if(arguments!!.getBoolean(ARG_START_POSTPONED_TRANSITION)) {
|
||||||
mediaActivity.onBringUp()
|
mediaActivity.onBringUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideToolbarAfterDelay(delayMilliseconds: Long) {
|
private fun hideToolbarAfterDelay(delayMilliseconds: Long) {
|
||||||
handler.postDelayed(hideToolbar, delayMilliseconds)
|
handler.postDelayed(hideToolbar, delayMilliseconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
toolbar = activity!!.toolbar
|
toolbar = activity!!.toolbar
|
||||||
mediaActivity = activity as ViewMediaActivity
|
mediaActivity = activity as ViewMediaActivity
|
||||||
return inflater.inflate(R.layout.fragment_view_video, container, false)
|
return inflater.inflate(R.layout.fragment_view_video, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
||||||
val attachment = arguments?.getParcelable<Attachment>(ARG_ATTACHMENT)
|
val attachment = arguments?.getParcelable<Attachment>(ARG_ATTACHMENT)
|
||||||
?: throw IllegalArgumentException("attachment has to be set")
|
?: throw IllegalArgumentException("attachment has to be set")
|
||||||
|
|
||||||
isAudio = (attachment.type == Attachment.Type.AUDIO)
|
isAudio = (attachment.type == Attachment.Type.AUDIO)
|
||||||
finalizeViewSetup(attachment.url, attachment.previewUrl, attachment.description)
|
finalizeViewSetup(attachment.url, attachment.previewUrl, attachment.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onToolbarVisibilityChange(visible: Boolean) {
|
override fun onToolbarVisibilityChange(visible: Boolean) {
|
||||||
if(videoView == null || mediaDescription == null || !userVisibleHint) {
|
if(videoView == null || mediaDescription == null || !userVisibleHint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isDescriptionVisible = showingDescription && visible
|
isDescriptionVisible = showingDescription && visible
|
||||||
val alpha = if(isDescriptionVisible) 1.0f else 0.0f
|
val alpha = if(isDescriptionVisible) 1.0f else 0.0f
|
||||||
if(isDescriptionVisible) {
|
if(isDescriptionVisible) {
|
||||||
// If to be visible, need to make visible immediately and animate alpha
|
// If to be visible, need to make visible immediately and animate alpha
|
||||||
mediaDescription.alpha = 0.0f
|
mediaDescription.alpha = 0.0f
|
||||||
mediaDescription.visible(isDescriptionVisible)
|
mediaDescription.visible(isDescriptionVisible)
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaDescription.animate().alpha(alpha)
|
mediaDescription.animate().alpha(alpha)
|
||||||
.setListener(object : AnimatorListenerAdapter() {
|
.setListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationEnd(animation: Animator) {
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
mediaDescription?.visible(isDescriptionVisible)
|
mediaDescription?.visible(isDescriptionVisible)
|
||||||
animation.removeListener(this)
|
animation.removeListener(this)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.start()
|
.start()
|
||||||
|
|
||||||
if(visible && (videoView.player?.isPlaying == true) && !isAudio) {
|
if(visible && (videoView.player?.isPlaying == true) && !isAudio) {
|
||||||
hideToolbarAfterDelay(TOOLBAR_HIDE_DELAY_MS)
|
hideToolbarAfterDelay(TOOLBAR_HIDE_DELAY_MS)
|
||||||
} else {
|
} else {
|
||||||
handler.removeCallbacks(hideToolbar)
|
handler.removeCallbacks(hideToolbar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTransitionEnd() {
|
override fun onTransitionEnd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
|
||||||
releasePlayer()
|
releasePlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
|
|
||||||
releasePlayer()
|
releasePlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun releasePlayer() {
|
private fun releasePlayer() {
|
||||||
exoPlayer?.run {
|
exoPlayer?.run {
|
||||||
playbackPosition = this.currentPosition
|
playbackPosition = this.currentPosition
|
||||||
currentWindow = this.currentWindowIndex
|
currentWindow = this.currentWindowIndex
|
||||||
playWhenReady = this.playWhenReady
|
playWhenReady = this.playWhenReady
|
||||||
removeListener(playbackStateListener)
|
removeListener(playbackStateListener)
|
||||||
release()
|
release()
|
||||||
}
|
}
|
||||||
exoPlayer = null
|
exoPlayer = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun playbackStateListener() = object : Player.Listener {
|
private fun playbackStateListener() = object : Player.Listener {
|
||||||
|
|
||||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
when(playbackState) {
|
when(playbackState) {
|
||||||
Player.STATE_BUFFERING -> {
|
Player.STATE_BUFFERING -> {
|
||||||
progressBar.visibility = View.VISIBLE
|
progressBar.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
Player.STATE_READY,
|
Player.STATE_READY,
|
||||||
Player.STATE_ENDED -> {
|
Player.STATE_ENDED -> {
|
||||||
progressBar.visibility = View.GONE
|
progressBar.visibility = View.GONE
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayerError(error: PlaybackException) {
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
Timber.e(error.errorCodeName)
|
Timber.e(error.errorCodeName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue