Commit 76a0bca0 authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Geoffrey Métais
Browse files

Migrate main activities to kotlin

parent 5143b824
......@@ -200,13 +200,13 @@ open class AudioPlayerContainerActivity : BaseActivity(), CoroutineScope by Main
fun showTipViewIfNeeded(stubId: Int, settingKey: String) {
if (BuildConfig.DEBUG) return
val vsc = findViewById<View>(stubId)
if (vsc != null && !mSettings.getBoolean(settingKey, false) && !AndroidDevices.showTvUi(this)) {
if (vsc != null && !settings.getBoolean(settingKey, false) && !AndroidDevices.showTvUi(this)) {
val v = (vsc as ViewStubCompat).inflate()
v.setOnClickListener { removeTipViewIfDisplayed() }
val okGotIt = v.findViewById<TextView>(R.id.okgotit_button)
okGotIt.setOnClickListener {
removeTipViewIfDisplayed()
val editor = mSettings.edit()
val editor = settings.edit()
editor.putBoolean(settingKey, true)
editor.apply()
}
......@@ -363,7 +363,7 @@ open class AudioPlayerContainerActivity : BaseActivity(), CoroutineScope by Main
fun proposeCard() = launch {
delay(1000L)
if (PlaylistManager.showAudioPlayer.value == true) return@launch
val song = mSettings.getString("current_song", null) ?: return@launch
val song = settings.getString("current_song", null) ?: return@launch
val media = getFromMl { getMedia(Uri.parse(song)) }
val title = media?.title ?: Uri.decode(FileUtils.getFileNameFromPath(song)).substringBeforeLast('.')
if (!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) return@launch
......
package org.videolan.vlc.gui;
import android.content.SharedPreferences;
import android.os.Bundle;
import org.videolan.vlc.R;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.Settings;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
public class BaseActivity extends AppCompatActivity {
protected SharedPreferences mSettings;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mSettings = Settings.INSTANCE.getInstance(this);
/* Theme must be applied before super.onCreate */
applyTheme();
super.onCreate(savedInstanceState);
}
private void applyTheme() {
if (AndroidDevices.showTvUi(this)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
setTheme(R.style.Theme_VLC_Black);
return;
}
if (mSettings.contains("app_theme")) {
AppCompatDelegate.setDefaultNightMode(Integer.valueOf(mSettings.getString("app_theme", "-1")));
} else if (mSettings.contains("daynight") || mSettings.contains("enable_black_theme")) { // legacy support
final boolean daynight = mSettings.getBoolean("daynight", false);
final boolean dark = mSettings.getBoolean("enable_black_theme", false);
final int mode = dark ? AppCompatDelegate.MODE_NIGHT_YES : daynight ? AppCompatDelegate.MODE_NIGHT_AUTO : AppCompatDelegate.MODE_NIGHT_NO;
AppCompatDelegate.setDefaultNightMode(mode);
}
}
}
package org.videolan.vlc.gui
import android.content.SharedPreferences
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import org.videolan.vlc.R
import org.videolan.vlc.util.AndroidDevices
import org.videolan.vlc.util.Settings
open class BaseActivity : AppCompatActivity() {
protected lateinit var settings: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
settings = Settings.getInstance(this)
/* Theme must be applied before super.onCreate */
applyTheme()
super.onCreate(savedInstanceState)
}
private fun applyTheme() {
if (AndroidDevices.showTvUi(this)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
setTheme(R.style.Theme_VLC_Black)
return
}
if (settings.contains("app_theme")) {
AppCompatDelegate.setDefaultNightMode(Integer.valueOf(settings.getString("app_theme", "-1")!!))
} else if (settings.contains("daynight") || settings.contains("enable_black_theme")) { // legacy support
val daynight = settings.getBoolean("daynight", false)
val dark = settings.getBoolean("enable_black_theme", false)
val mode = if (dark) AppCompatDelegate.MODE_NIGHT_YES else if (daynight) AppCompatDelegate.MODE_NIGHT_AUTO else AppCompatDelegate.MODE_NIGHT_NO
AppCompatDelegate.setDefaultNightMode(mode)
}
}
}
package org.videolan.vlc.gui;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.videolan.libvlc.util.VLCUtil;
import org.videolan.vlc.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class CompatErrorActivity extends Activity {
public final static String TAG = "VLC/CompatErrorActivity";
/**
* Simple friendly activity to tell the user something's wrong.
*
* Intent parameters (all optional):
* runtimeError (bool) - Set to true if you want to show a runtime error
* (defaults to a compatibility error)
* message (string) - the more detailed problem
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.not_compatible);
String errorMsg = VLCUtil.getErrorMsg();
if(getIntent().getBooleanExtra("runtimeError", false))
if(getIntent().getStringExtra("message") != null) {
errorMsg = getIntent().getStringExtra("message");
TextView tvo = (TextView)findViewById(R.id.message);
tvo.setText(R.string.error_problem);
}
TextView tv = (TextView)findViewById(R.id.errormsg);
tv.setText(getResources().getString(R.string.error_message_is) + "\n" + errorMsg);
}
}
package org.videolan.vlc.gui
import android.app.Activity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import org.videolan.libvlc.util.VLCUtil
import org.videolan.vlc.R
class CompatErrorActivity : Activity() {
/**
* Simple friendly activity to tell the user something's wrong.
*
* Intent parameters (all optional):
* runtimeError (bool) - Set to true if you want to show a runtime error
* (defaults to a compatibility error)
* message (string) - the more detailed problem
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.not_compatible)
var errorMsg = VLCUtil.getErrorMsg()
if (intent.getBooleanExtra("runtimeError", false))
if (intent.getStringExtra("message") != null) {
errorMsg = intent.getStringExtra("message")
val tvo = findViewById<View>(R.id.message) as TextView
tvo.setText(R.string.error_problem)
}
val tv = findViewById<View>(R.id.errormsg) as TextView
tv.text = resources.getString(R.string.error_message_is) + "\n" + errorMsg
}
companion object {
const val TAG = "VLC/CompatErrorActivity"
}
}
/*
* *************************************************************************
* ContentActivity.java
* **************************************************************************
* Copyright © 2017 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui;
import android.annotation.SuppressLint;
import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import org.videolan.libvlc.RendererItem;
import org.videolan.vlc.PlaybackService;
import org.videolan.vlc.R;
import org.videolan.vlc.RendererDelegate;
import org.videolan.vlc.gui.audio.AudioBrowserFragment;
import org.videolan.vlc.gui.browser.ExtensionBrowser;
import org.videolan.vlc.gui.browser.MediaBrowserFragment;
import org.videolan.vlc.gui.dialogs.RenderersDialog;
import org.videolan.vlc.gui.folders.FoldersFragment;
import org.videolan.vlc.gui.helpers.UiTools;
import org.videolan.vlc.gui.video.VideoGridFragment;
import org.videolan.vlc.interfaces.Filterable;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.Settings;
import org.videolan.vlc.util.Util;
import java.util.List;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SearchView;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
@SuppressLint("Registered")
public class ContentActivity extends AudioPlayerContainerActivity implements SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
public static final String TAG = "VLC/ContentActivity";
private SearchView mSearchView;
private boolean showRenderers = !AndroidDevices.isChromeBook && !Util.isListEmpty(RendererDelegate.INSTANCE.getRenderers().getValue());
@Override
protected void initAudioPlayerContainerActivity() {
super.initAudioPlayerContainerActivity();
if (!AndroidDevices.isChromeBook && !AndroidDevices.isAndroidTv
&& Settings.INSTANCE.getInstance(this).getBoolean("enable_casting", true)) {
PlaybackService.Companion.getRenderer().observe(this, new Observer<RendererItem>() {
@Override
public void onChanged(@Nullable RendererItem rendererItem) {
final MenuItem item = getToolbar().getMenu().findItem(R.id.ml_menu_renderers);
if (item == null) return;
item.setVisible(showRenderers);
item.setIcon(!PlaybackService.Companion.hasRenderer() ? R.drawable.ic_am_renderer_normal_w : R.drawable.ic_am_renderer_on_w);
}
});
RendererDelegate.INSTANCE.getRenderers().observe(this, new Observer<List<RendererItem>>() {
@Override
public void onChanged(@Nullable List<RendererItem> rendererItems) {
showRenderers = !Util.isListEmpty(rendererItems);
final MenuItem item = getToolbar().getMenu().findItem(R.id.ml_menu_renderers);
if (item != null) item.setVisible(showRenderers);
}
});
}
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
UiTools.setOnDragListener(this);
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
if (AndroidDevices.isAndroidTv) return false;
final Fragment current = getCurrentFragment();
super.onCreateOptionsMenu(menu);
if (current instanceof AboutFragment) return true;
getMenuInflater().inflate(R.menu.activity_option, menu);
if (current instanceof ExtensionBrowser){
menu.findItem(R.id.ml_menu_last_playlist).setVisible(false);
menu.findItem(R.id.ml_menu_sortby).setVisible(false);
}
if (current instanceof Filterable) {
final Filterable filterable = (Filterable) current;
final MenuItem searchItem = menu.findItem(R.id.ml_menu_filter);
mSearchView = (SearchView) searchItem.getActionView();
mSearchView.setQueryHint(getString(R.string.search_list_hint));
mSearchView.setOnQueryTextListener(this);
final String query = filterable.getFilterQuery();
if (!TextUtils.isEmpty(query)) {
getActivityHandler().post(new Runnable() {
@Override
public void run() {
searchItem.expandActionView();
mSearchView.clearFocus();
UiTools.setKeyboardVisibility(mSearchView, false);
mSearchView.setQuery(query, false);
}
});
}
searchItem.setOnActionExpandListener(this);
} else menu.findItem(R.id.ml_menu_filter).setVisible(false);
menu.findItem(R.id.ml_menu_renderers).setVisible(showRenderers && Settings.INSTANCE.getInstance(this).getBoolean("enable_casting", true));
menu.findItem(R.id.ml_menu_renderers).setIcon(!PlaybackService.Companion.hasRenderer() ? R.drawable.ic_am_renderer_normal_w : R.drawable.ic_am_renderer_on_w);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.ml_menu_search:
startActivity(new Intent(Intent.ACTION_SEARCH, null, this, SearchActivity.class));
return true;
case R.id.ml_menu_renderers:
if (!PlaybackService.Companion.hasRenderer()
&& RendererDelegate.INSTANCE.getRenderers().getValue().size() == 1) {
final RendererItem renderer = RendererDelegate.INSTANCE.getRenderers().getValue().get(0);
PlaybackService.Companion.getRenderer().setValue(renderer);
final View v = findViewById(R.id.audio_player_container);
if (v != null) UiTools.snacker(v, getString(R.string.casting_connected_renderer, renderer.displayName));
} else if (getSupportFragmentManager().findFragmentByTag("renderers") == null)
new RenderersDialog().show(getSupportFragmentManager(), "renderers");
return true;
case R.id.ml_menu_filter:
if (!item.isActionViewExpanded()) setSearchVisibility(true);
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onQueryTextChange(String filterQueryString) {
final Fragment current = getCurrentFragment();
if (current instanceof Filterable) {
if (filterQueryString.length() < 3) ((Filterable) current).restoreList();
else ((Filterable) current).filter(filterQueryString);
return true;
}
return false;
}
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
setSearchVisibility(true);
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
setSearchVisibility(false);
restoreCurrentList();
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
public void openSearchActivity() {
startActivity(new Intent(Intent.ACTION_SEARCH, null, this, SearchActivity.class)
.putExtra(SearchManager.QUERY, mSearchView.getQuery().toString()));
}
private void setSearchVisibility(boolean visible) {
final Fragment current = getCurrentFragment();
if (current instanceof Filterable) {
((Filterable) current).setSearchVisibility(visible);
makeRoomForSearch(current, visible);
}
}
// Hide options menu items to make room for filter EditText
protected void makeRoomForSearch(Fragment current, boolean hide) {
final Menu menu = getToolbar().getMenu();
final MenuItem renderersItem = menu.findItem(R.id.ml_menu_renderers);
if (renderersItem != null) renderersItem.setVisible(!hide && showRenderers);
if (current instanceof MediaBrowserFragment) {
final MenuItem sortItem = menu.findItem(R.id.ml_menu_sortby);
if (sortItem != null) sortItem.setVisible(!hide && ((MediaBrowserFragment) current).getViewModel().canSortByName());
}
if (current instanceof VideoGridFragment || current instanceof AudioBrowserFragment
|| current instanceof FoldersFragment) {
final MenuItem lastItem = menu.findItem(R.id.ml_menu_last_playlist);
if (lastItem != null) lastItem.setVisible(!hide);
}
}
public void onClick(View v) {
if (v.getId() == R.id.searchButton) openSearchActivity();
}
public void closeSearchView() {
if (getToolbar().getMenu() != null) {
final MenuItem item = getToolbar().getMenu().findItem(R.id.ml_menu_filter);
if (item != null) item.collapseActionView();
}
}
public void restoreCurrentList() {
final Fragment current = getCurrentFragment();
if (current instanceof Filterable) {
((Filterable) current).restoreList();
}
}
}
/*
* *************************************************************************
* ContentActivity.java
* **************************************************************************
* Copyright © 2017 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui
import android.annotation.SuppressLint
import android.app.SearchManager
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.libvlc.RendererItem
import org.videolan.vlc.PlaybackService
import org.videolan.vlc.R
import org.videolan.vlc.RendererDelegate
import org.videolan.vlc.gui.audio.AudioBrowserFragment
import org.videolan.vlc.gui.browser.ExtensionBrowser
import org.videolan.vlc.gui.browser.MediaBrowserFragment
import org.videolan.vlc.gui.dialogs.RenderersDialog
import org.videolan.vlc.gui.folders.FoldersFragment
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.video.VideoGridFragment
import org.videolan.vlc.interfaces.Filterable
import org.videolan.vlc.util.AndroidDevices
import org.videolan.vlc.util.Settings
import org.videolan.vlc.util.Util
@ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi
@SuppressLint("Registered")
open class ContentActivity : AudioPlayerContainerActivity(), SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
private var mSearchView: SearchView? = null
private var showRenderers = !AndroidDevices.isChromeBook && !Util.isListEmpty(RendererDelegate.renderers.value)
override fun initAudioPlayerContainerActivity() {
super.initAudioPlayerContainerActivity()
if (!AndroidDevices.isChromeBook && !AndroidDevices.isAndroidTv
&& Settings.getInstance(this).getBoolean("enable_casting", true)) {
PlaybackService.renderer.observe(this, Observer {
val item = toolbar.menu.findItem(R.id.ml_menu_renderers) ?: return@Observer
item.isVisible = showRenderers
item.setIcon(if (!PlaybackService.hasRenderer()) R.drawable.ic_am_renderer_normal_w else R.drawable.ic_am_renderer_on_w)
})
RendererDelegate.renderers.observe(this, Observer<List<RendererItem>> { rendererItems ->
showRenderers = !Util.isListEmpty(rendererItems)
val item = toolbar.menu.findItem(R.id.ml_menu_renderers)
if (item != null) item.isVisible = showRenderers
})
}
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
UiTools.setOnDragListener(this)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
if (AndroidDevices.isAndroidTv) return false
val current = currentFragment
super.onCreateOptionsMenu(menu)
if (current is AboutFragment) return true
menuInflater.inflate(R.menu.activity_option, menu)
if (current is ExtensionBrowser) {
menu.findItem(R.id.ml_menu_last_playlist).isVisible = false
menu.findItem(R.id.ml_menu_sortby).isVisible = false
}
if (current is Filterable) {
val filterable = current as Filterable?
val searchItem = menu.findItem(R.id.ml_menu_filter)
mSearchView = searchItem.actionView as SearchView
mSearchView!!.queryHint = getString(R.string.search_list_hint)
mSearchView!!.setOnQueryTextListener(this)
val query = filterable!!.filterQuery
if (!TextUtils.isEmpty(query)) {
activityHandler.post {
searchItem.expandActionView()
mSearchView!!.clearFocus()
UiTools.setKeyboardVisibility(mSearchView, false)
mSearchView!!.setQuery(query, false)
}
}
searchItem.setOnActionExpandListener(this)
} else
menu.findItem(R.id.ml_menu_filter).isVisible = false
menu.findItem(R.id.ml_menu_renderers).isVisible = showRenderers && Settings.getInstance(this).getBoolean("enable_casting", true)
menu.findItem(R.id.ml_menu_renderers).setIcon(if (!PlaybackService.hasRenderer()) R.drawable.ic_am_renderer_normal_w else R.drawable.ic_am_renderer_on_w)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.ml_menu_search -> {
startActivity(Intent(Intent.ACTION_SEARCH, null, this, SearchActivity::class.java))
return true
}
R.id.ml_menu_renderers -> {
if (!PlaybackService.hasRenderer() && RendererDelegate.renderers.value.size == 1) {
val renderer = RendererDelegate.renderers.value[0]
PlaybackService.renderer.value = renderer
val v = findViewById<View>(R.id.audio_player_container)
if (v != null) UiTools.snacker(v, getString(R.string.casting_connected_renderer, renderer.displayName))
} else if (supportFragmentManager.findFragmentByTag("renderers") == null)
RenderersDialog().show(supportFragmentManager, "renderers")
return true
}
R.id.ml_menu_filter -> {
if (!item.isActionViewExpanded) setSearchVisibility(true)
return super.onOptionsItemSelected(item)
}
else -> return super.onOptionsItemSelected(item)
}
}
override fun onQueryTextChange(filterQueryString: String): Boolean {
val current = currentFragment
if (current is Filterable) {
if (filterQueryString.length < 3)
(current as Filterable).restoreList()
else
(current as Filterable).filter(filterQueryString)