Codebase merged from master

This commit is contained in:
subhadipThinkpad 2018-12-31 22:37:36 +05:30
parent 3e97ec2529
commit 6535ac37c3
56 changed files with 1347 additions and 217 deletions

13
CHANGELOG.md Normal file
View File

@ -0,0 +1,13 @@
### Version 1.0.18 Tag: v1.0.18 (2018-12-31)
* Bug Fixes
* Arabic translation update
* Dependence update
### Version 1.0.17 Tag: v1.0.17 (2018-12-29)
* Replaced more buttons with fonts
* Translated app to Chinese. (@lishoujun)
### Version 1.0.16 Tag: v1.0.16 (2018-12-28)
* Fullscreen button
* Local Videos
* Bug Fixes

View File

@ -24,12 +24,12 @@ Beta Test on Google Play: https://play.google.com/store/apps/details?id=net.schu
- [X] Change Server - [X] Change Server
- [X] Search - [X] Search
- [X] App Icon and assets - [X] App Icon and assets
- [!] Themes / Dark mode (needs work) - [X] Themes / Dark mode
- [X] Background playback - [X] Background playback
- [X] NSFW Filter option - [X] NSFW Filter option
# TODO ## TODO
- [ ] Video Playback via WebRTC - [ ] Video Playback via WebRTC
- [ ] Authentication / Login - [ ] Authentication / Login

View File

@ -6,8 +6,8 @@ android {
applicationId "net.schueller.peertube" applicationId "net.schueller.peertube"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 28
versionCode 1012 versionCode 1018
versionName "1.0.12" versionName "1.0.18"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
@ -26,18 +26,18 @@ android {
implementation 'com.mikepenz:fontawesome-typeface:5.3.1.1@aar' implementation 'com.mikepenz:fontawesome-typeface:5.3.1.1@aar'
// http client / REST // http client / REST
implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.squareup.okhttp3:okhttp:3.12.1'
implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.retrofit2:retrofit:2.5.0'
// image downloading and caching library // image downloading and caching library
implementation 'com.squareup.picasso:picasso:2.5.2' implementation 'com.squareup.picasso:picasso:2.5.2'
// json decoder/encoder // json decoder/encoder
implementation 'com.google.code.gson:gson:2.8.2' implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
// Torrents and WebRTC // Torrents and WebRTC
implementation 'com.github.TorrentStream:TorrentStream-Android:2.5.0' implementation 'com.github.TorrentStream:TorrentStream-Android:2.6.1'
// implementation "com.github.TorrentStream:TorrentStreamServer-Android:1.0.1" // implementation "com.github.TorrentStream:TorrentStreamServer-Android:1.0.1"
// implementation 'org.webrtc:google-webrtc:1.0.+' // implementation 'org.webrtc:google-webrtc:1.0.+'
@ -47,6 +47,7 @@ android {
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.2' implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.2'
implementation 'com.google.android.exoplayer:exoplayer-hls:2.9.2' implementation 'com.google.android.exoplayer:exoplayer-hls:2.9.2'
implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.9.2' implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.9.2'
implementation 'com.google.android.exoplayer:extension-mediasession:2.9.2'
// testing // testing
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import android.content.res.Configuration; import android.content.res.Configuration;

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@ -23,6 +41,8 @@ import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
public class SettingsActivity extends AppCompatPreferenceActivity { public class SettingsActivity extends AppCompatPreferenceActivity {
private static String previousThemeColorValue = "";
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
@ -33,6 +53,21 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private static String getSelectedColor(Context context, String colorId){
String res = "Color not found";
String [ ] themeArray = context.getResources().getStringArray(R.array.themeValues);
String [ ] colorArray = context.getResources().getStringArray(R.array.themeArray);
for (int i = 0 ; i < themeArray.length ; i++){
if (themeArray[i].equals(colorId)){
res = colorArray[i];
break;
}
}
return res;
}
/** /**
* A preference value change listener that updates the preference's summary * A preference value change listener that updates the preference's summary
* to reflect its new value. * to reflect its new value.
@ -45,6 +80,19 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
Toast.makeText(preference.getContext(), R.string.invalid_url, Toast.LENGTH_LONG).show(); Toast.makeText(preference.getContext(), R.string.invalid_url, Toast.LENGTH_LONG).show();
return false; return false;
} }
// Check if Theme color has change & Provide selected color
else if (preference.getKey().equals("pref_theme")) {
stringValue = getSelectedColor(preference.getContext(), stringValue);
if (!previousThemeColorValue.equals("") && !previousThemeColorValue.equals(stringValue)) {
Toast.makeText(preference.getContext(), R.string.pref_description_app_theme, Toast.LENGTH_LONG).show();
}
previousThemeColorValue = stringValue;
preference.setSummary(stringValue);
return true;
}
preference.setSummary(stringValue); preference.setSummary(stringValue);
@ -96,7 +144,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
setupActionBar(); setupActionBar();
getFragmentManager().beginTransaction().replace(android.R.id.content, new GeneralPreferenceFragment()).commit(); getFragmentManager().beginTransaction().replace(android.R.id.content, new GeneralPreferenceFragment()).commit();
} }
/** /**
@ -153,6 +200,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// updated to reflect the new value, per the Android Design // updated to reflect the new value, per the Android Design
// guidelines. // guidelines.
bindPreferenceSummaryToValue(findPreference("pref_api_base")); bindPreferenceSummaryToValue(findPreference("pref_api_base"));
bindPreferenceSummaryToValue(findPreference("pref_theme"));
} }
@Override @Override

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import android.Manifest; import android.Manifest;
@ -38,6 +56,7 @@ import net.schueller.peertube.model.VideoList;
import net.schueller.peertube.network.GetVideoDataService; import net.schueller.peertube.network.GetVideoDataService;
import net.schueller.peertube.network.RetrofitInstance; import net.schueller.peertube.network.RetrofitInstance;
import net.schueller.peertube.provider.SearchSuggestionsProvider; import net.schueller.peertube.provider.SearchSuggestionsProvider;
import net.schueller.peertube.service.VideoPlayerService;
import java.util.ArrayList; import java.util.ArrayList;
@ -61,7 +80,7 @@ public class VideoListActivity extends AppCompatActivity {
private int currentStart = 0; private int currentStart = 0;
private int count = 12; private int count = 12;
private String sort = "-createdAt"; private String sort = "-createdAt";
private String filter = ""; private String filter = null;
private String searchQuery = ""; private String searchQuery = "";
private TextView emptyView; private TextView emptyView;
@ -89,7 +108,7 @@ public class VideoListActivity extends AppCompatActivity {
setContentView(R.layout.activity_video_list); setContentView(R.layout.activity_video_list);
filter = ""; filter = null;
createBottomBarNavigation(); createBottomBarNavigation();
@ -151,6 +170,11 @@ public class VideoListActivity extends AppCompatActivity {
return true; return true;
} }
@Override
protected void onDestroy() {
super.onDestroy();
stopService(new Intent(this, VideoPlayerService.class));
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
@ -236,9 +260,9 @@ public class VideoListActivity extends AppCompatActivity {
Call<VideoList> call; Call<VideoList> call;
if (!searchQuery.equals("")) { if (!searchQuery.equals("")) {
call = service.searchVideosData(start, count, sort, nsfw, searchQuery); call = service.searchVideosData(start, count, sort, nsfw, searchQuery, filter);
} else { } else {
call = service.getVideosData(start, count, sort, nsfw); call = service.getVideosData(start, count, sort, nsfw, filter);
} }
/*Log the URL called*/ /*Log the URL called*/
@ -339,6 +363,8 @@ public class VideoListActivity extends AppCompatActivity {
new IconicsDrawable(this, FontAwesome.Icon.faw_home)); new IconicsDrawable(this, FontAwesome.Icon.faw_home));
navMenu.findItem(R.id.navigation_trending).setIcon( navMenu.findItem(R.id.navigation_trending).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_fire)); new IconicsDrawable(this, FontAwesome.Icon.faw_fire));
navMenu.findItem(R.id.navigation_local).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_home));
navMenu.findItem(R.id.navigation_subscriptions).setIcon( navMenu.findItem(R.id.navigation_subscriptions).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_folder)); new IconicsDrawable(this, FontAwesome.Icon.faw_folder));
navMenu.findItem(R.id.navigation_account).setIcon( navMenu.findItem(R.id.navigation_account).setIcon(
@ -353,6 +379,7 @@ public class VideoListActivity extends AppCompatActivity {
if (!isLoading) { if (!isLoading) {
sort = "-createdAt"; sort = "-createdAt";
currentStart = 0; currentStart = 0;
filter = null;
loadVideos(currentStart, count, sort, filter); loadVideos(currentStart, count, sort, filter);
} }
@ -363,6 +390,18 @@ public class VideoListActivity extends AppCompatActivity {
if (!isLoading) { if (!isLoading) {
sort = "-trending"; sort = "-trending";
currentStart = 0; currentStart = 0;
filter = null;
loadVideos(currentStart, count, sort, filter);
}
return true;
case R.id.navigation_local:
//Log.v(TAG, "navigation_trending");
if (!isLoading) {
sort = "-publishedAt";
filter = "local";
currentStart = 0;
loadVideos(currentStart, count, sort, filter); loadVideos(currentStart, count, sort, filter);
} }

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import android.content.ComponentName; import android.content.ComponentName;
@ -5,6 +23,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -16,6 +35,7 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import android.util.Log; import android.util.Log;
import android.util.TypedValue;
import android.view.Surface; import android.view.Surface;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -35,11 +55,14 @@ import com.github.se_bastiaan.torrentstream.TorrentStream;
import com.github.se_bastiaan.torrentstream.listeners.TorrentListener; import com.github.se_bastiaan.torrentstream.listeners.TorrentListener;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.PlayerView; import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoRendererEventListener; import com.google.android.exoplayer2.video.VideoRendererEventListener;
import com.mikepenz.iconics.Iconics;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import net.schueller.peertube.R; import net.schueller.peertube.R;
import net.schueller.peertube.fragment.VideoOptionsFragment;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.MetaDataHelper; import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.intents.Intents; import net.schueller.peertube.intents.Intents;
@ -52,6 +75,7 @@ import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
import static net.schueller.peertube.helper.Constants.BACKGROUND_PLAY_PREF_KEY;
import static net.schueller.peertube.helper.Constants.DEFAULT_THEME; import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY; import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
@ -63,6 +87,8 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
private PlayerView simpleExoPlayerView; private PlayerView simpleExoPlayerView;
private Intent videoPlayerIntent; private Intent videoPlayerIntent;
private Context context = this; private Context context = this;
private TextView fullscreenButton;
private Boolean isFullscreen = false;
boolean mBound = false; boolean mBound = false;
VideoPlayerService mService; VideoPlayerService mService;
@ -110,8 +136,27 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
simpleExoPlayerView = new PlayerView(this); simpleExoPlayerView = new PlayerView(this);
simpleExoPlayerView = findViewById(R.id.video_view); simpleExoPlayerView = findViewById(R.id.video_view);
videoPlayerIntent = new Intent(this, VideoPlayerService.class); simpleExoPlayerView.setControllerShowTimeoutMs(1000);
bindService(videoPlayerIntent, mConnection, Context.BIND_AUTO_CREATE); simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
// Full screen Icon
fullscreenButton = findViewById(R.id.exo_fullscreen);
fullscreenButton.setText(R.string.video_expand_icon);
new Iconics.IconicsBuilder().ctx(this).on(fullscreenButton).build();
fullscreenButton.setOnClickListener(view -> {
Log.d(TAG, "Fullscreen");
if (!isFullscreen) {
isFullscreen = true;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
fullscreenButton.setText(R.string.video_compress_icon);
} else {
isFullscreen = false;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
fullscreenButton.setText(R.string.video_expand_icon);
}
new Iconics.IconicsBuilder().ctx(this).on(fullscreenButton).build();
});
} }
@ -203,7 +248,7 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) simpleExoPlayerView.getLayoutParams(); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) simpleExoPlayerView.getLayoutParams();
params.width = ViewGroup.LayoutParams.MATCH_PARENT; params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.WRAP_CONTENT; params.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, getResources().getDisplayMetrics());
simpleExoPlayerView.setLayoutParams(params); simpleExoPlayerView.setLayoutParams(params);
nameView.setVisibility(View.VISIBLE); nameView.setVisibility(View.VISIBLE);
@ -241,13 +286,9 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
TextView videoOwner = findViewById(R.id.videoOwner); TextView videoOwner = findViewById(R.id.videoOwner);
TextView videoMeta = findViewById(R.id.videoMeta); TextView videoMeta = findViewById(R.id.videoMeta);
ImageView avatarView = findViewById(R.id.avatar); ImageView avatarView = findViewById(R.id.avatar);
ImageButton moreButton = findViewById(R.id.moreButton); TextView moreButton = findViewById(R.id.moreButton);
TextView videoOptions = findViewById(R.id.exo_more);
//Playback speed buttons
Button speed05 = findViewById(R.id.speed05);
Button speed10 = findViewById(R.id.speed10);
Button speed15 = findViewById(R.id.speed15);
Button speed20 = findViewById(R.id.speed20);
Video video = response.body(); Video video = response.body();
@ -279,6 +320,9 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
); );
videoDescription.setText(video.getDescription()); videoDescription.setText(video.getDescription());
moreButton.setText(R.string.video_more_icon);
new Iconics.IconicsBuilder().ctx(context).on(moreButton).build();
moreButton.setOnClickListener(v -> { moreButton.setOnClickListener(v -> {
PopupMenu popup = new PopupMenu(context, v); PopupMenu popup = new PopupMenu(context, v);
popup.setOnMenuItemClickListener(menuItem -> { popup.setOnMenuItemClickListener(menuItem -> {
@ -294,42 +338,20 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
popup.show(); popup.show();
}); });
// video player options
videoOptions.setText(R.string.video_more_icon);
new Iconics.IconicsBuilder().ctx(context).on(videoOptions).build();
videoOptions.setOnClickListener(v -> {
VideoOptionsFragment videoOptionsFragment =
VideoOptionsFragment.newInstance(mService);
videoOptionsFragment.show(getSupportFragmentManager(),
"video_options_fragment");
});
mService.setCurrentStreamUrl(video.getFiles().get(0).getFileUrl()); mService.setCurrentStreamUrl(video.getFiles().get(0).getFileUrl());
//Playback speed controls
speed05.setOnClickListener(view -> {
mService.setPlayBackSpeed(0.5f);
speed05.setTextColor(getResources().getColor(R.color.primaryColorRed));
speed10.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed15.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed20.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
});
speed10.setOnClickListener(view -> {
mService.setPlayBackSpeed(1.0f);
speed10.setTextColor(getResources().getColor(R.color.primaryColorRed));
speed05.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed15.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed20.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
});
speed15.setOnClickListener(view -> {
mService.setPlayBackSpeed(1.5f);
speed15.setTextColor(getResources().getColor(R.color.primaryColorRed));
speed05.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed10.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed20.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
});
speed20.setOnClickListener(view -> {
mService.setPlayBackSpeed(2.0f);
speed20.setTextColor(getResources().getColor(R.color.primaryColorRed));
speed05.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed10.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
speed15.setTextColor(getResources().getColor(R.color.secondaryTextColorRed));
});
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if (sharedPref.getBoolean("pref_torrent_player", false)) { if (sharedPref.getBoolean("pref_torrent_player", false)) {
@ -409,6 +431,16 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
// SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
//
// Log.v(TAG, "" + sharedPref.getBoolean(BACKGROUND_PLAY_PREF_KEY, false));
//
// if (!sharedPref.getBoolean(BACKGROUND_PLAY_PREF_KEY, false)) {
// Log.v(TAG, "BACKGROUND_PLAY_PREF_KEY...");
// stopService(new Intent(this, VideoPlayerService.class));
// }
if (mBound) { if (mBound) {
unbindService(mConnection); unbindService(mConnection);
mBound = false; mBound = false;
@ -419,6 +451,11 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
if (!mBound) {
videoPlayerIntent = new Intent(this, VideoPlayerService.class);
bindService(videoPlayerIntent, mConnection, Context.BIND_AUTO_CREATE);
}
Log.v(TAG, "onStart()..."); Log.v(TAG, "onStart()...");
} }

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.adapter; package net.schueller.peertube.adapter;
import android.content.Context; import android.content.Context;
@ -5,6 +22,8 @@ import android.content.Intent;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.content.pm.ActivityInfo;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -12,6 +31,7 @@ import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.mikepenz.iconics.Iconics;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import net.schueller.peertube.R; import net.schueller.peertube.R;
@ -94,6 +114,9 @@ public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHol
}); });
holder.moreButton.setText(R.string.video_more_icon);
new Iconics.IconicsBuilder().ctx(context).on(holder.moreButton).build();
holder.moreButton.setOnClickListener(v -> { holder.moreButton.setOnClickListener(v -> {
PopupMenu popup = new PopupMenu(context, v); PopupMenu popup = new PopupMenu(context, v);
@ -130,9 +153,8 @@ public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHol
class VideoViewHolder extends RecyclerView.ViewHolder { class VideoViewHolder extends RecyclerView.ViewHolder {
TextView name, videoMeta, videoOwner; TextView name, videoMeta, videoOwner, moreButton;
ImageView thumb, avatar; ImageView thumb, avatar;
ImageButton moreButton;
View mView; View mView;
VideoViewHolder(View itemView) { VideoViewHolder(View itemView) {

View File

@ -0,0 +1,95 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.mikepenz.iconics.Iconics;
import net.schueller.peertube.R;
import net.schueller.peertube.service.VideoPlayerService;
import androidx.annotation.Nullable;
public class VideoOptionsFragment extends BottomSheetDialogFragment {
private static VideoPlayerService videoPlayerService;
private TextView speed05Icon;
private TextView speed10Icon;
private TextView speed15Icon;
private TextView speed20Icon;
public static VideoOptionsFragment newInstance(VideoPlayerService mService) {
videoPlayerService = mService;
return new VideoOptionsFragment();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_video_options_fragment, container,
false);
// Icons
speed05Icon = view.findViewById(R.id.video_speed05_icon);
speed10Icon = view.findViewById(R.id.video_speed10_icon);
speed15Icon = view.findViewById(R.id.video_speed15_icon);
speed20Icon = view.findViewById(R.id.video_speed20_icon);
// Buttons
TextView speed05 = view.findViewById(R.id.video_speed05);
TextView speed10 = view.findViewById(R.id.video_speed10);
TextView speed15 = view.findViewById(R.id.video_speed15);
TextView speed20 = view.findViewById(R.id.video_speed20);
// Default
setVideoSpeed(1.0f, speed10Icon);
// Attach the listener
speed05.setOnClickListener(v -> setVideoSpeed(0.5f, speed05Icon));
speed10.setOnClickListener(v -> setVideoSpeed(1.0f, speed10Icon));
speed15.setOnClickListener(v -> setVideoSpeed(1.5f, speed15Icon));
speed20.setOnClickListener(v -> setVideoSpeed(2.0f, speed20Icon));
return view;
}
private void setVideoSpeed(Float speed, TextView icon) {
speed05Icon.setText("");
speed10Icon.setText("");
speed15Icon.setText("");
speed20Icon.setText("");
videoPlayerService.setPlayBackSpeed(speed);
icon.setText(R.string.video_speed_active_icon);
new Iconics.IconicsBuilder().ctx(getContext()).on(icon).build();
}
}

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.helper; package net.schueller.peertube.helper;
import android.content.Context; import android.content.Context;

View File

@ -1,6 +1,24 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.helper; package net.schueller.peertube.helper;
public class Constants { public class Constants {
public static final String THEME_PREF_KEY = "pref_theme"; public static final String THEME_PREF_KEY = "pref_theme";
public static final String DEFAULT_THEME = "AppTheme.ORANGE"; public static final String DEFAULT_THEME = "AppTheme.ORANGE";
public static final String BACKGROUND_PLAY_PREF_KEY = "pref_background_play";
} }

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.helper; package net.schueller.peertube.helper;
import android.content.Context; import android.content.Context;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.intents; package net.schueller.peertube.intents;
import android.content.Context; import android.content.Context;

View File

@ -1,3 +1,21 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
import java.util.Date; import java.util.Date;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
import java.util.Date; import java.util.Date;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Category { public class Category {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
import java.util.Date; import java.util.Date;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Config { public class Config {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class File { public class File {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Language { public class Language {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Licence { public class Licence {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class OauthClient { public class OauthClient {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Privacy { public class Privacy {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Resolution { public class Resolution {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Server { public class Server {

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
public class Token { public class Token {

View File

@ -1,8 +1,38 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.media.MediaDescriptionCompat;
import com.squareup.picasso.Picasso;
import net.schueller.peertube.R;
import net.schueller.peertube.helper.APIUrlHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import androidx.annotation.DrawableRes;
public class Video { public class Video {
private Integer id; private Integer id;
@ -247,4 +277,31 @@ public class Video {
public void setFiles(ArrayList<File> files) { public void setFiles(ArrayList<File> files) {
this.files = files; this.files = files;
} }
public static MediaDescriptionCompat getMediaDescription(Context context, Video video) {
// String apiBaseURL = APIUrlHelper.getUrlWithVersion(context);
// Bundle extras = new Bundle();
// Bitmap bitmap = getBitmap(context, Uri.parse(apiBaseURL + video.thumbnailPath));
// extras.putParcelable(MediaDescriptionCompat.DESCRIPTION_KEY_MEDIA_URI, bitmap);
return new MediaDescriptionCompat.Builder()
.setMediaId(video.getUuid())
// .setIconBitmap(bitmap)
// .setExtras(extras)
.setTitle(video.getName())
.setDescription(video.getDescription())
.build();
}
// TODO: add support for the thumbnail
// public static Bitmap getBitmap(Context context, Uri fullThumbnailUrl) {
//
// return Picasso.with(context).load(fullThumbnailUrl)
// .placeholder(R.drawable.ic_peertube)
// .error(R.drawable.ic_peertube).get();
// }
} }

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model; package net.schueller.peertube.model;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.network; package net.schueller.peertube.network;
import net.schueller.peertube.model.OauthClient; import net.schueller.peertube.model.OauthClient;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.network; package net.schueller.peertube.network;
import net.schueller.peertube.model.Config; import net.schueller.peertube.model.Config;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.network; package net.schueller.peertube.network;
import net.schueller.peertube.model.ServerList; import net.schueller.peertube.model.ServerList;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.network; package net.schueller.peertube.network;
import net.schueller.peertube.model.Video; import net.schueller.peertube.model.Video;
@ -14,8 +31,8 @@ public interface GetVideoDataService {
@Query("start") int start, @Query("start") int start,
@Query("count") int count, @Query("count") int count,
@Query("sort") String sort, @Query("sort") String sort,
@Query("nsfw") String nsfw @Query("nsfw") String nsfw,
//@Query("filter") String filter @Query("filter") String filter
); );
@GET("videos/{id}") @GET("videos/{id}")
@ -29,7 +46,7 @@ public interface GetVideoDataService {
@Query("count") int count, @Query("count") int count,
@Query("sort") String sort, @Query("sort") String sort,
@Query("nsfw") String nsfw, @Query("nsfw") String nsfw,
@Query("search") String search @Query("search") String search,
// @Query("filter") String filter @Query("filter") String filter
); );
} }

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.network; package net.schueller.peertube.network;
import retrofit2.Retrofit; import retrofit2.Retrofit;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.provider; package net.schueller.peertube.provider;
import android.content.SearchRecentSuggestionsProvider; import android.content.SearchRecentSuggestionsProvider;

View File

@ -1,3 +1,20 @@
/*
* Copyright 2018 Stefan Schüller <sschueller@techdroid.com>
*
* License: GPL-3.0+
* 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 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, see <http://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.service; package net.schueller.peertube.service;
import android.app.Notification; import android.app.Notification;
@ -11,14 +28,22 @@ import android.graphics.Bitmap;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.support.v4.media.MediaDescriptionCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlayerNotificationManager; import com.google.android.exoplayer2.ui.PlayerNotificationManager;
@ -37,6 +62,9 @@ import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID;
public class VideoPlayerService extends Service { public class VideoPlayerService extends Service {
private static final String TAG = "VideoPlayerService";
private static final String MEDIA_SESSION_TAG = "peertube_player";
private final IBinder mBinder = new LocalBinder(); private final IBinder mBinder = new LocalBinder();
private static final String PLAYBACK_CHANNEL_ID = "playback_channel"; private static final String PLAYBACK_CHANNEL_ID = "playback_channel";
@ -64,12 +92,12 @@ public class VideoPlayerService extends Service {
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ACTION_PAUSE) { // this means that pause is available, hence the audio is playing if (playbackState == ACTION_PAUSE) { // this means that pause is available, hence the audio is playing
Log.v("VideoPlayerService", "ACTION_PLAY: " + playbackState); Log.v(TAG, "ACTION_PLAY: " + playbackState);
registerReceiver(myNoisyAudioStreamReceiver, becomeNoisyIntentFilter); registerReceiver(myNoisyAudioStreamReceiver, becomeNoisyIntentFilter);
} }
if (playbackState == ACTION_PLAY) { // this means that play is available, hence the audio is paused or stopped if (playbackState == ACTION_PLAY) { // this means that play is available, hence the audio is paused or stopped
Log.v("VideoPlayerService", "ACTION_PAUSE: " + playbackState); Log.v(TAG, "ACTION_PAUSE: " + playbackState);
unregisterReceiver(myNoisyAudioStreamReceiver); unregisterReceiver(myNoisyAudioStreamReceiver);
} }
} }
@ -89,12 +117,14 @@ public class VideoPlayerService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
Log.v("VideoPlayerService", "onDestroy..."); Log.v(TAG, "onDestroy...");
if (playerNotificationManager != null) {
playerNotificationManager.setPlayer(null); playerNotificationManager.setPlayer(null);
player.release(); }
player = null; if (player != null) {
player.release();
player = null;
}
super.onDestroy(); super.onDestroy();
} }
@ -106,7 +136,7 @@ public class VideoPlayerService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("VideoPlayerService", "onStartCommand..."); Log.v(TAG, "onStartCommand...");
playVideo(); playVideo();
return START_STICKY; return START_STICKY;
} }
@ -114,27 +144,27 @@ public class VideoPlayerService extends Service {
public void setCurrentVideo(Video video) public void setCurrentVideo(Video video)
{ {
Log.v("VideoPlayerService", "setCurrentVideo..."); Log.v(TAG, "setCurrentVideo...");
currentVideo = video; currentVideo = video;
} }
public void setCurrentStreamUrl(String streamUrl) public void setCurrentStreamUrl(String streamUrl)
{ {
Log.v("VideoPlayerService", "setCurrentStreamUrl..."); Log.v(TAG, "setCurrentStreamUrl...");
currentStreamUrl = streamUrl; currentStreamUrl = streamUrl;
} }
//Playback speed control //Playback speed control
public void setPlayBackSpeed(float speed) { public void setPlayBackSpeed(float speed) {
Log.v("VideoPlayerService", "setPlayBackSpeed..."); Log.v(TAG, "setPlayBackSpeed...");
player.setPlaybackParameters(new PlaybackParameters(speed)); player.setPlaybackParameters(new PlaybackParameters(speed));
} }
public void playVideo() { public void playVideo() {
Context context = this; Context context = this;
Log.v("VideoPlayerService", "playVideo..."); Log.v(TAG, "playVideo...");
// Produces DataSource instances through which media data is loaded. // Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(), DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(),
@ -203,7 +233,7 @@ public class VideoPlayerService extends Service {
@Override @Override
public void onNotificationCancelled(int notificationId) { public void onNotificationCancelled(int notificationId) {
Log.v("VideoPlayerService", "onNotificationCancelled..."); Log.v(TAG, "onNotificationCancelled...");
// TODO: only kill the notification if we no longer have a bound activity // TODO: only kill the notification if we no longer have a bound activity
stopForeground(true); stopForeground(true);
@ -213,6 +243,26 @@ public class VideoPlayerService extends Service {
playerNotificationManager.setPlayer(player); playerNotificationManager.setPlayer(player);
// external Media control, Android Wear / Google Home etc.
MediaSessionCompat mediaSession = new MediaSessionCompat(context, MEDIA_SESSION_TAG);
mediaSession.setActive(true);
playerNotificationManager.setMediaSessionToken(mediaSession.getSessionToken());
MediaSessionConnector mediaSessionConnector = new MediaSessionConnector(mediaSession);
mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
@Override
public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
return Video.getMediaDescription(context, currentVideo);
}
});
mediaSessionConnector.setPlayer(player, null);
// Audio Focus
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MOVIE)
.build();
player.setAudioAttributes(audioAttributes,true);
} }
// pause playback on audio output change // pause playback on audio output change
@ -225,4 +275,5 @@ public class VideoPlayerService extends Service {
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

View File

@ -17,11 +17,11 @@
android:id="@+id/video_view" android:id="@+id/video_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="250dp" android:layout_height="250dp"
android:background="@color/videoBackgroundColor"
app:resize_mode="fixed_width"
app:controller_layout_id="@layout/video_playback_controls"
app:layout_constraintDimensionRatio="H,3:1" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar <ProgressBar
android:id="@+id/progress" android:id="@+id/progress"
@ -86,16 +86,19 @@
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/> />
<ImageButton <TextView
android:id="@+id/moreButton" android:id="@+id/moreButton"
android:layout_width="wrap_content" android:layout_width="45dp"
android:layout_height="45dp" android:layout_height="45dp"
android:layout_below="@+id/thumb"
android:layout_marginTop="16dp"
android:layout_marginStart="-16dp" android:layout_marginStart="-16dp"
android:layout_marginEnd="0dp" android:layout_marginEnd="0dp"
android:layout_toEndOf="@+id/name" android:layout_toEndOf="@+id/name"
android:background="@null" android:background="@null"
android:contentDescription="@string/descr_overflow_button" android:contentDescription="@string/descr_overflow_button"
android:src="@drawable/ic_action_more_vert" /> android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
<TextView <TextView
android:id="@+id/description" android:id="@+id/description"
@ -108,54 +111,10 @@
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Body1" /> android:textAppearance="@style/Base.TextAppearance.AppCompat.Body1" />
<TextView
android:id="@+id/playback_speed_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/description"
android:text="Playback Speed"
android:layout_marginTop="16dp"/>
<Button
android:id="@+id/speed05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/playback_speed_label"
android:text="0.5x"
android:textAllCaps="false"/>
<Button
android:id="@+id/speed10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/playback_speed_label"
android:layout_toRightOf="@id/speed05"
android:text="1.0x"
android:textAllCaps="false"
android:textColor="@color/primaryColorRed"
/>
<Button
android:id="@+id/speed15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/playback_speed_label"
android:layout_toRightOf="@id/speed10"
android:text="1.5x"
android:textAllCaps="false"/>
<Button
android:id="@+id/speed20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/playback_speed_label"
android:layout_toRightOf="@id/speed15"
android:text="2.0x"
android:textAllCaps="false"/>
</RelativeLayout> </RelativeLayout>
</RelativeLayout>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,127 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@color/videoBackgroundColor"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/video_speed05_icon"
android:layout_width="32dp"
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:gravity="center|start"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="12sp" />
<TextView
android:id="@+id/video_speed05"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:gravity="center|start"
android:text="@string/video_speed_05"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/video_speed10_icon"
android:layout_width="32dp"
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:gravity="center|start"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="12sp" />
<TextView
android:id="@+id/video_speed10"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:gravity="center|start"
android:text="@string/video_speed_10"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/video_speed15_icon"
android:layout_width="32dp"
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:gravity="center|start"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="12sp" />
<TextView
android:id="@+id/video_speed15"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:gravity="center|start"
android:text="@string/video_speed_15"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/video_speed20_icon"
android:layout_width="32dp"
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:gravity="center|start"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="12sp" />
<TextView
android:id="@+id/video_speed20"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:gravity="center|start"
android:text="@string/video_speed_20"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layoutDirection="ltr"
android:background="#CC000000"
android:orientation="vertical"
tools:targetApi="28">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="4dp"
android:orientation="horizontal">
<ImageButton android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind"/>
<ImageButton android:id="@id/exo_shuffle"
style="@style/ExoMediaButton.Shuffle"/>
<ImageButton android:id="@id/exo_repeat_toggle"
style="@style/ExoMediaButton"/>
<ImageButton android:id="@id/exo_play"
style="@style/ExoMediaButton.Play"/>
<ImageButton android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause"/>
<ImageButton android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:includeFontPadding="false"
android:textColor="#FFBEBEBE"/>
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@id/exo_progress"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="26dp"/>
<TextView android:id="@id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:includeFontPadding="false"
android:textColor="#FFBEBEBE"/>
</LinearLayout>
</LinearLayout>

View File

@ -72,20 +72,19 @@
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/> />
<ImageButton <TextView
android:id="@+id/moreButton" android:id="@+id/moreButton"
android:layout_width="wrap_content" android:layout_width="45dp"
android:layout_height="45dp" android:layout_height="45dp"
android:layout_below="@+id/thumb" android:layout_below="@+id/thumb"
android:layout_marginTop="16dp"
android:layout_marginStart="-16dp" android:layout_marginStart="-16dp"
android:layout_marginEnd="0dp" android:layout_marginEnd="0dp"
android:layout_toEndOf="@+id/name" android:layout_toEndOf="@+id/name"
android:background="@null" android:background="@null"
android:contentDescription="@string/descr_overflow_button" android:contentDescription="@string/descr_overflow_button"
android:src="@drawable/ic_action_more_vert" /> android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
</RelativeLayout> </RelativeLayout>

View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#CC000000"
android:layoutDirection="ltr"
android:orientation="vertical"
tools:targetApi="28">
<FrameLayout
android:id="@+id/exo_more_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="end">
<TextView
android:id="@+id/exo_more"
android:layout_width="18dp"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:paddingTop="12dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:textColor="#FFBEBEBE"
android:textSize="12sp" />
</FrameLayout>
<View
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="4dp">
<ImageButton
android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind" />
<ImageButton
android:id="@id/exo_repeat_toggle"
style="@style/ExoMediaButton" />
<ImageButton
android:id="@id/exo_play"
style="@style/ExoMediaButton.Play" />
<ImageButton
android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause" />
<ImageButton
android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward" />
</LinearLayout>
<View
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="bottom"
android:orientation="horizontal">
<TextView
android:id="@id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:layout_gravity="center"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textColor="#FFBEBEBE"
android:textSize="14sp" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:layout_gravity="center"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:textColor="#FFBEBEBE"
android:textSize="14sp" />
<FrameLayout
android:id="@+id/exo_fullscreen_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="end">
<TextView
android:id="@+id/exo_fullscreen"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:textColor="#FFBEBEBE"
android:textSize="12sp" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="bottom"
android:orientation="horizontal">
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@id/exo_progress"
android:layout_width="0dp"
android:layout_height="26dp"
android:layout_weight="1"
app:played_color="?attr/colorPrimary" />
</LinearLayout>
</LinearLayout>

View File

@ -12,6 +12,11 @@
android:title="@string/bottom_nav_title_trending" android:title="@string/bottom_nav_title_trending"
app:showAsAction="always|withText"/> app:showAsAction="always|withText"/>
<item
android:id="@+id/navigation_local"
android:title="@string/bottom_nav_title_local"
app:showAsAction="ifRoom|withText"/>
<item <item
android:id="@+id/navigation_subscriptions" android:id="@+id/navigation_subscriptions"
android:title="@string/bottom_nav_title_subscriptions" android:title="@string/bottom_nav_title_subscriptions"

View File

@ -9,12 +9,14 @@
android:orderInCategory="300" android:orderInCategory="300"
android:title="@string/action_bar_title_search" android:title="@string/action_bar_title_search"
app:showAsAction="always|collapseActionView" app:showAsAction="always|collapseActionView"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
app:actionViewClass="androidx.appcompat.widget.SearchView" /> app:actionViewClass="androidx.appcompat.widget.SearchView" />
<item <item
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:orderInCategory="300" android:orderInCategory="300"
android:title="@string/action_bar_title_settings" android:title="@string/action_bar_title_settings"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
</menu> </menu>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_video_playback_speed"
android:icon="@drawable/ic_action_share"
android:title="@string/menu_share" />
</menu>

View File

@ -1,4 +1,3 @@
<!-- File "app/src/main/res/values/strings.xml" -->
<resources> <resources>
<string name="app_name">PeerTube</string> <string name="app_name">PeerTube</string>
@ -36,8 +35,8 @@
<!-- Strings related to Video meta data --> <!-- Strings related to Video meta data -->
<string name="meta_data_seperator">\u0020-\u0020</string> <string name="meta_data_seperator">\0020-\0020</string>
<string name="meta_data_views">\u0020مشاهدات</string> <string name="meta_data_views">\0020مشاهدات</string>
<string name="meta_data_owner_seperator">\@</string> <string name="meta_data_owner_seperator">\@</string>
@ -45,14 +44,14 @@
<string name="video_row_account_avatar">الصورة الرمزية للحساب</string> <string name="video_row_account_avatar">الصورة الرمزية للحساب</string>
<string name="pref_title_show_nsfw">عرض NSFW</string> <string name="pref_title_show_nsfw">عرض NSFW</string>
<string name="pref_description_show_nsfw">عند التفعيل سيتم عرض محتويات NSFW</string> <string name="pref_description_show_nsfw">عند التنشيط سيتم عرض محتويات NSFW</string>
<string name="title_activity_url_video_play">UrlVideoPlayActivity</string> <string name="title_activity_url_video_play">UrlVideoPlayActivity</string>
<string name="pref_title_torrent_player">مشغل فديو التورنت</string> <string name="pref_title_torrent_player">مشغل فيديو التورنت</string>
<string name="pref_description_torrent_player">تشغيل الفيديو عبر بث التورنت . يتطلب هذا أذونات التخزين. (ألفا ، غير مستقر!)</string> <string name="pref_description_torrent_player">تشغيل الفيديو عبر بث التورنت . يتطلب هذا أذونات التخزين. (ألفا ، غير مستقر!)</string>
<string name="pref_title_license">الرخصة</string> <string name="pref_title_license">الرخصة</string>
<string name="pref_description_license"><b >GNU Affero General Public License v3.0</b>\n <string name="pref_description_license"><b >GNU Affero General Public License v3.0</b>\n
\n \n
إن أذونات هذا الترخيص الأقوى للحقوق المتروكة مشروطة بإتاحة الشفرة المصدرية الكاملة للأعمال والتعديلات المرخصة ، والتي تشتمل على أعمال أكبر باستخدام عمل مرخص ، تحت نفس الترخيص. يجب الحفاظ على حقوق النشر وإشعارات الترخيص. يقدم المساهمون منحة صريحة لحقوق البراءة. عند استخدام إصدار معدل لتوفير خدمة عبر شبكة ، يجب توفير شفرة المصدر الكاملة للإصدار المعدل.</string> إن أذونات هذا الترخيص الأقوى للحقوق المتروكة مشروطة بإتاحة الشفرة المصدرية الكاملة للأعمال والتعديلات المرخصة ، والتي تشتمل على أعمال أكبر باستخدام عمل مرخص ، تحت نفس الترخيص. يجب الحفاظ على حقوق النشر وإشعارات الترخيص. يقدم المساهمون منحة صريحة لحقوق البراءة. عند استخدام إصدار معدل لتوفير خدمة عبر شبكة ، يجب توفير شفرة المصدر الكاملة للإصدار المعدل.</string>
<string name="pref_title_version">الإصدار</string> <string name="pref_title_version">الإصدار</string>
<string name="search_hint">مشاركة PeerTube</string> <string name="search_hint">مشاركة PeerTube</string>
<string name="title_activity_search">بحث</string> <string name="title_activity_search">بحث</string>
@ -60,5 +59,39 @@
<string name="descr_overflow_button">المزيد</string> <string name="descr_overflow_button">المزيد</string>
<string name="menu_share">مشاركة</string> <string name="menu_share">مشاركة</string>
<string name="playback_channel_name">PeerTube</string> <string name="playback_channel_name">PeerTube</string>
<string name="invalid_url">الرابط غير صالح!</string>
<string name="pref_title_dark_mode">الوضع الداكن</string>
<string name="pref_description_dark_mode">أعد تشغيل التطبيق لتنشيط الوضع الداكن.</string>
<string name="pref_title_app_theme">مظهر التطبيق</string>
<string name="pref_description_app_theme">أعد تشغيل التطبيق لتفعيل التعديلات التي طرأت على المظهر.</string>
<string name="red">أحمر</string>
<string name="pink">وردي</string>
<string name="purple">بنفسجي</string>
<string name="deeppurple">بنفسجي قاتم</string>
<string name="indigo">نيلي</string>
<string name="blue">أزرق</string>
<string name="lightblue">أزرق فاتح</string>
<string name="cyan">سماوي</string>
<string name="teal">أزرق مُخضرّ</string>
<string name="green">أخضر</string>
<string name="lightgreen">أخضر فاتح</string>
<string name="lime">جيري</string>
<string name="yellow">أصفر</string>
<string name="amber">كهرماني</string>
<string name="orange">برتقالي</string>
<string name="deeporange">برتقالي قاتم</string>
<string name="brown">قهوي</string>
<string name="gray">رمادي</string>
<string name="bluegray">أزرق رمادي</string>
<string name="video_speed_05">0.5x</string>
<string name="video_speed_10">عادي</string>
<string name="video_speed_15">1.5x</string>
<string name="video_speed_20">2x</string>
<string name="pref_title_background_play">التشغيل في الخلفية</string>
<string name="pref_description_background_play">إن تم تنشيطه، ستواصل الفيديو في الإشتغال في الخلفية.</string>
<string name="bottom_nav_title_local">المحلي</string>
</resources> </resources>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">PeerTube</string>
<string name="action_sign_in_short">登录</string>
<string name="action_sign_in">登录</string>
<string name="title_activity_login">登录</string>
<string name="prompt_server">服务</string>
<string name="title_activity_settings">设置</string>
<string name="action_bar_title_search">搜索</string>
<string name="bottom_nav_title_home">主页</string>
<string name="bottom_nav_title_trending">趋势</string>
<string name="bottom_nav_title_subscriptions">订阅</string>
<string name="bottom_nav_title_account">帐号</string>
<string name="descr_overflow_button">更多</string>
<string name="menu_share">分享</string>
<string name="pref_title_peertube_server">PeerTube 服务器</string>
<string name="pref_title_show_nsfw">显示NSFW</string>
<string name="pref_title_version">版本</string>
<string name="prompt_email">邮箱</string>
<string name="prompt_password">密码(可选)</string>
<string name="search_hint">建议</string>
<string name="title_activity_search">搜索</string>
<string name="video_speed_10">正常</string>
<string name="video_speed_05">0.5倍速</string>
<string name="video_speed_15">1.5倍速</string>
<string name="video_speed_20">2倍速</string>
<string name="yellow">黄色</string>
<string name="red">红色</string>
<string name="action_bar_title_settings">设置</string>
<string name="error_invalid_email">邮箱格式错误</string>
<string name="error_invalid_password">密码过短</string>
<string name="error_incorrect_password">密码错误</string>
<string name="pref_description_show_nsfw">点亮按钮以显示成人内容</string>
<string name="pref_title_app_theme">主题</string>
<string name="pref_description_app_theme">重启应用该主题</string>
<string name="pref_description_dark_mode">重启进入夜间模式</string>
<string name="pref_title_dark_mode">夜间模式</string>
<string name="invalid_url">URL错误</string>
<string name="amber">琥珀色</string>
<string name="pink">粉红</string>
<string name="purple">紫色</string>
<string name="deeppurple">暗绛红</string>
<string name="indigo">靛青</string>
<string name="blue">蓝色</string>
<string name="lightblue">浅青</string>
<string name="cyan">青色</string>
<string name="teal">鸭翅绿</string>
<string name="no_data_available">无结果</string>
<string name="pref_title_license">许可</string>
<string name="lightgreen">浅绿</string>
<string name="green">正绿</string>
<string name="lime">青柠色</string>
<string name="orange">橙色</string>
<string name="deeporange">深橙色</string>
<string name="brown">褐色</string>
<string name="gray">灰色</string>
<string name="bluegray">蓝灰色</string>
<string name="meta_data_views">次观看</string>
</resources>

View File

@ -4,6 +4,7 @@
<color name="themeDeselected">#d69b9b9b</color> <color name="themeDeselected">#d69b9b9b</color>
<color name="themeSelected">#e300aaff</color> <color name="themeSelected">#e300aaff</color>
<color name="seperator">#7ca6a6a6</color> <color name="seperator">#7ca6a6a6</color>
<color name="videoBackgroundColor">#000000</color>
<!-- RED Theme --> <!-- RED Theme -->

View File

@ -84,5 +84,18 @@
<string name="brown">Brown</string> <string name="brown">Brown</string>
<string name="gray">Gray</string> <string name="gray">Gray</string>
<string name="bluegray">Bluegray</string> <string name="bluegray">Bluegray</string>
<string name="video_speed_05">0.5x</string>
<string name="video_speed_10">Normal</string>
<string name="video_speed_15">1.5x</string>
<string name="video_speed_20">2x</string>
<string name="video_speed_active_icon">{faw-check}</string>
<string name="video_expand_icon">{faw-expand}</string>
<string name="video_compress_icon">{faw-compress}</string>
<string name="video_more_icon">{faw-ellipsis-v}</string>
<string name="pref_title_background_play">Background Playback</string>
<string name="pref_description_background_play">If enabled, continues to play video in background.</string>
<string name="bottom_nav_title_local">Local</string>
</resources> </resources>

View File

@ -10,6 +10,12 @@
android:singleLine="true" android:singleLine="true"
android:title="@string/pref_title_peertube_server" /> android:title="@string/pref_title_peertube_server" />
<!--<SwitchPreference-->
<!--android:key="pref_background_play"-->
<!--android:title="@string/pref_title_background_play"-->
<!--android:summary="@string/pref_description_background_play"-->
<!--android:defaultValue="true" />-->
<SwitchPreference <SwitchPreference
android:key="pref_show_nsfw" android:key="pref_show_nsfw"
android:title="@string/pref_title_show_nsfw" android:title="@string/pref_title_show_nsfw"
@ -20,7 +26,7 @@
android:title="@string/pref_title_app_theme" android:title="@string/pref_title_app_theme"
android:summary="@string/pref_description_app_theme" android:summary="@string/pref_description_app_theme"
android:key="pref_theme" android:key="pref_theme"
android:defaultValue="1" android:defaultValue="AppTheme.ORANGE"
android:entries="@array/themeArray" android:entries="@array/themeArray"
android:entryValues="@array/themeValues" /> android:entryValues="@array/themeValues" />