Merge pull request #117 from sschueller/develop

Release v1.0.25
This commit is contained in:
Stefan Schüller 2019-01-20 18:14:38 +01:00 committed by GitHub
commit b46a09fc37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1603 additions and 140 deletions

View File

@ -1,3 +1,7 @@
### Version 1.0.25 Tag: v1.0.25 (2019-01-20)
* Account overview page and videos list
* Turkish (tr) Translation added (@oktay454)
### Version 1.0.24 Tag: v1.0.24 (2019-01-09)
* Set video quality (@digiwizkid)
* BN Strings update (@digiwizkid)

View File

@ -6,8 +6,8 @@ android {
applicationId "net.schueller.peertube"
minSdkVersion 21
targetSdkVersion 28
versionCode 1024
versionName "1.0.24"
versionCode 1025
versionName "1.0.25"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ext {
libVersions = [

View File

@ -52,10 +52,12 @@
<activity android:name=".activity.SelectServerActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".activity.AccountActivity"
<activity android:name=".activity.MeActivity"
android:label="@string/title_activity_account"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".activity.AccountActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<!-- Content provider for search suggestions -->
<provider

View File

@ -18,79 +18,138 @@
package net.schueller.peertube.activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
import com.mikepenz.iconics.IconicsDrawable;
import net.schueller.peertube.R;
import net.schueller.peertube.adapter.ChannelAdapter;
import net.schueller.peertube.adapter.VideoAdapter;
import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.model.Me;
import net.schueller.peertube.model.OauthClient;
import net.schueller.peertube.model.Token;
import net.schueller.peertube.network.AuthenticationService;
import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.model.Account;
import net.schueller.peertube.model.ChannelList;
import net.schueller.peertube.model.VideoList;
import net.schueller.peertube.network.GetUserService;
import net.schueller.peertube.network.GetVideoDataService;
import net.schueller.peertube.network.RetrofitInstance;
import net.schueller.peertube.network.Session;
import java.util.ArrayList;
import java.util.Set;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
public class AccountActivity extends CommonActivity {
private String TAG = "AccountActivity";
private String apiBaseURL;
private static final String TAG = "AccountActivity";
private Integer videosStart, videosCount, videosCurrentStart;
private String videosFilter, videosSort, videosNsfw;
private Set<String> videosLanguages;
private ChannelAdapter channelAdapter;
private VideoAdapter videoAdapter;
private RecyclerView recyclerViewVideos;
private RecyclerView recyclerViewChannels;
private SwipeRefreshLayout swipeRefreshLayoutVideos;
private SwipeRefreshLayout swipeRefreshLayoutChannels;
private CoordinatorLayout aboutView;
//private TextView emptyView;
private Boolean isLoadingVideos;
private GetUserService userService;
private String displayNameAndHost;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_top_user, menu);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set an icon in the ActionBar
menu.findItem(R.id.action_logout).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_sign_out_alt).actionBar());
setContentView(R.layout.activity_account);
return true;
}
apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
userService = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class);
recyclerViewVideos = findViewById(R.id.account_video_recyclerView);
recyclerViewChannels = findViewById(R.id.account_channel_recyclerView);
swipeRefreshLayoutVideos = findViewById(R.id.account_swipeRefreshLayout_videos);
swipeRefreshLayoutChannels = findViewById(R.id.account_swipeRefreshLayout_channels);
aboutView = findViewById(R.id.account_about);
RecyclerView.LayoutManager layoutManagerVideos = new LinearLayoutManager(AccountActivity.this);
recyclerViewVideos.setLayoutManager(layoutManagerVideos);
RecyclerView.LayoutManager layoutManagerVideosChannels = new LinearLayoutManager(AccountActivity.this);
recyclerViewChannels.setLayoutManager(layoutManagerVideosChannels);
videoAdapter = new VideoAdapter(new ArrayList<>(), AccountActivity.this);
recyclerViewVideos.setAdapter(videoAdapter);
channelAdapter = new ChannelAdapter(new ArrayList<>(), AccountActivity.this);
recyclerViewChannels.setAdapter(channelAdapter);
@Override
public boolean onOptionsItemSelected(MenuItem item) {
swipeRefreshLayoutVideos.setOnRefreshListener(() -> {
// Refresh items
if (!isLoadingVideos) {
videosCurrentStart = 0;
loadAccountVideos(displayNameAndHost);
}
});
switch (item.getItemId()) {
// action with ID action_refresh was selected
// get video ID
Intent intent = getIntent();
displayNameAndHost = intent.getStringExtra(VideoListActivity.EXTRA_ACCOUNTDISPLAYNAME);
Log.v(TAG, "click: " + displayNameAndHost);
case R.id.action_logout:
Session.getInstance().invalidate();
Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
this.startActivity(intent);
finish();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
createBottomBarNavigation();
videosStart = 0;
videosCount = 25;
videosCurrentStart = 0;
videosFilter = "";
videosSort = "-publishedAt";
videosNsfw = "";
// Attaching the layout to the toolbar object
Toolbar toolbar = findViewById(R.id.tool_bar_account);
// Setting toolbar as the ActionBar with setSupportActionBar() call
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(displayNameAndHost);
getSupportActionBar().setHomeAsUpIndicator(
new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
);
loadAccountVideos(displayNameAndHost);
}
@Override
@ -100,76 +159,178 @@ public class AccountActivity extends CommonActivity {
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
private void loadAccount(String ownerString) {
setContentView(R.layout.activity_account);
// get video details from api
Call<Account> call = userService.getAccount(ownerString);
// Attaching the layout to the toolbar object
Toolbar toolbar = findViewById(R.id.tool_bar_user);
// Setting toolbar as the ActionBar with setSupportActionBar() call
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(
new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
);
init();
}
private void init() {
// try to get user data
getUserData();
}
private boolean getUserData() {
// TODO
String apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
GetUserService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class);
Call<Me> call = service.getMe();
call.enqueue(new Callback<Me>() {
call.enqueue(new Callback<Account>() {
@Override
public void onResponse(@NonNull Call<Me> call, @NonNull Response<Me> response) {
public void onResponse(@NonNull Call<Account> call, @NonNull Response<Account> response) {
if (response.isSuccessful()) {
Account account = response.body();
Me me = response.body();
String owner = MetaDataHelper.getOwnerString(account.getName(),
account.getHost(),
AccountActivity.this
);
TextView username = findViewById(R.id.account_username);
TextView email = findViewById(R.id.account_email);
// set view data
TextView ownerStringView = findViewById(R.id.account_owner_string);
ownerStringView.setText(owner);
username.setText(me.getUsername());
email.setText(me.getEmail());
TextView followers = findViewById(R.id.account_followers);
followers.setText(account.getFollowersCount().toString());
Log.v(TAG, me.getEmail());
TextView description = findViewById(R.id.account_description);
description.setText(account.getDescription());
TextView joined = findViewById(R.id.account_joined);
joined.setText(account.getCreatedAt().toString());
} else {
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<Me> call, Throwable t) {
public void onFailure(@NonNull Call<Account> call, @NonNull Throwable t) {
Log.wtf(TAG, t.fillInStackTrace());
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
}
});
return true;
}
@Override
protected void onResume() {
super.onResume();
init();
private void loadAccountVideos(String displayNameAndHost) {
isLoadingVideos = false;
GetVideoDataService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetVideoDataService.class);
Call<VideoList> call;
call = service.getAccountVideosData(displayNameAndHost, videosStart, videosCount, videosSort);
call.enqueue(new Callback<VideoList>() {
@Override
public void onResponse(@NonNull Call<VideoList> call, @NonNull Response<VideoList> response) {
Log.v(TAG, response.toString());
if (response.isSuccessful()) {
if (videosCurrentStart == 0) {
videoAdapter.clearData();
}
if (response.body() != null) {
videoAdapter.setData(response.body().getVideoArrayList());
}
} else{
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
}
isLoadingVideos = false;
swipeRefreshLayoutVideos.setRefreshing(false);
}
@Override
public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) {
Log.wtf("err", t.fillInStackTrace());
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
isLoadingVideos = false;
swipeRefreshLayoutVideos.setRefreshing(false);
}
});
}
private void loadAccountChannels(String displayNameAndHost) {
// get video details from api
Call<ChannelList> call = userService.getAccountChannels(displayNameAndHost);
call.enqueue(new Callback<ChannelList>() {
@Override
public void onResponse(@NonNull Call<ChannelList> call, @NonNull Response<ChannelList> response) {
if (response.isSuccessful()) {
ChannelList channelList = response.body();
} else {
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NonNull Call<ChannelList> call, @NonNull Throwable t) {
Log.wtf(TAG, t.fillInStackTrace());
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
}
});
}
private void createBottomBarNavigation() {
// Get Bottom Navigation
BottomNavigationView navigation = findViewById(R.id.account_navigation);
// Always show text label
navigation.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
// Add Icon font
Menu navMenu = navigation.getMenu();
navMenu.findItem(R.id.account_navigation_about).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_user));
navMenu.findItem(R.id.account_navigation_channels).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_list));
navMenu.findItem(R.id.account_navigation_videos).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_video));
// Click Listener
navigation.setOnNavigationItemSelectedListener(menuItem -> {
switch (menuItem.getItemId()) {
case R.id.account_navigation_about:
swipeRefreshLayoutVideos.setVisibility(View.GONE);
swipeRefreshLayoutChannels.setVisibility(View.GONE);
aboutView.setVisibility(View.VISIBLE);
loadAccount(displayNameAndHost);
return true;
case R.id.account_navigation_channels:
swipeRefreshLayoutVideos.setVisibility(View.GONE);
swipeRefreshLayoutChannels.setVisibility(View.VISIBLE);
aboutView.setVisibility(View.GONE);
loadAccountChannels(displayNameAndHost);
return true;
case R.id.account_navigation_videos:
swipeRefreshLayoutVideos.setVisibility(View.VISIBLE);
swipeRefreshLayoutChannels.setVisibility(View.GONE);
aboutView.setVisibility(View.GONE);
loadAccountVideos(displayNameAndHost);
return true;
}
return false;
});
}
}

View File

@ -40,15 +40,11 @@ import net.schueller.peertube.network.AuthenticationService;
import net.schueller.peertube.network.RetrofitInstance;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
public class LoginActivity extends CommonActivity {
private String TAG = "LoginActivity";
@ -103,6 +99,15 @@ public class LoginActivity extends CommonActivity {
String email = mEmailView.getText().toString();
String password = mPasswordView.getText().toString();
//check values
if (email.isEmpty()) {
Toast.makeText(LoginActivity.this, "Email/Username is empty", Toast.LENGTH_LONG).show();
return;
}
if (password.isEmpty()) {
Toast.makeText(LoginActivity.this, "Password is empty", Toast.LENGTH_LONG).show();
return;
}
// make http call to login and save access tokens
String apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
@ -148,7 +153,7 @@ public class LoginActivity extends CommonActivity {
Log.wtf(TAG, "Logged in");
Intent intent = new Intent(context, AccountActivity.class);
Intent intent = new Intent(context, MeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

View File

@ -0,0 +1,162 @@
/*
* 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;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
import com.mikepenz.iconics.IconicsDrawable;
import net.schueller.peertube.R;
import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.model.Me;
import net.schueller.peertube.network.GetUserService;
import net.schueller.peertube.network.RetrofitInstance;
import net.schueller.peertube.network.Session;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MeActivity extends CommonActivity {
private static final String TAG = "MeActivity";
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_top_account, menu);
// Set an icon in the ActionBar
menu.findItem(R.id.action_logout).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_sign_out_alt).actionBar());
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// action with ID action_refresh was selected
case R.id.action_logout:
Session.getInstance().invalidate();
Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
this.startActivity(intent);
finish();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onSupportNavigateUp() {
finish(); // close this activity as oppose to navigating up
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_me);
// Attaching the layout to the toolbar object
Toolbar toolbar = findViewById(R.id.tool_bar_me);
// Setting toolbar as the ActionBar with setSupportActionBar() call
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(
new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
);
init();
}
private void init() {
// try to get user data
getUserData();
}
private boolean getUserData() {
// TODO
String apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
GetUserService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class);
Call<Me> call = service.getMe();
call.enqueue(new Callback<Me>() {
@Override
public void onResponse(@NonNull Call<Me> call, @NonNull Response<Me> response) {
if (response.isSuccessful()) {
Me me = response.body();
TextView username = findViewById(R.id.account_username);
TextView email = findViewById(R.id.account_email);
username.setText(me.getUsername());
email.setText(me.getEmail());
Log.v(TAG, me.getEmail());
}
}
@Override
public void onFailure(Call<Me> call, Throwable t) {
}
});
return true;
}
@Override
protected void onResume() {
super.onResume();
init();
}
}

View File

@ -70,7 +70,8 @@ public class VideoListActivity extends CommonActivity {
private String TAG = "VideoListActivity";
public static final String EXTRA_VIDEOID = "VIDEOID ";
public static final String EXTRA_VIDEOID = "VIDEOID";
public static final String EXTRA_ACCOUNTDISPLAYNAME = "ACCOUNTDISPLAYNAMEANDHOST";
private VideoAdapter videoAdapter;
private SwipeRefreshLayout swipeRefreshLayout;
@ -288,7 +289,7 @@ public class VideoListActivity extends CommonActivity {
@Override
public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) {
Log.wtf("err", t.fillInStackTrace());
Toast.makeText(VideoListActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
Toast.makeText(VideoListActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show();
isLoading = false;
swipeRefreshLayout.setRefreshing(false);
}
@ -427,7 +428,7 @@ public class VideoListActivity extends CommonActivity {
Intent intent = new Intent(this, LoginActivity.class);
this.startActivity(intent);
} else {
Intent intent = new Intent(this, AccountActivity.class);
Intent intent = new Intent(this, MeActivity.class);
this.startActivity(intent);
}

View File

@ -0,0 +1,175 @@
/*
* 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;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.mikepenz.iconics.Iconics;
import com.squareup.picasso.Picasso;
import net.schueller.peertube.R;
import net.schueller.peertube.activity.VideoPlayActivity;
import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.intents.Intents;
import net.schueller.peertube.model.Avatar;
import net.schueller.peertube.model.Video;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID;
public class ChannelAdapter extends RecyclerView.Adapter<ChannelAdapter.AccountViewHolder> {
private ArrayList<Video> videoList;
private Context context;
private String baseUrl;
public ChannelAdapter(ArrayList<Video> videoList, Context context) {
this.videoList = videoList;
this.context = context;
}
@NonNull
@Override
public AccountViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.row_account_video, parent, false);
baseUrl = APIUrlHelper.getUrl(context);
return new AccountViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull AccountViewHolder holder, int position) {
Picasso.with(this.context)
.load(baseUrl + videoList.get(position).getPreviewPath())
.into(holder.thumb);
Avatar avatar = videoList.get(position).getAccount().getAvatar();
if (avatar != null) {
String avatarPath = avatar.getPath();
Picasso.with(this.context)
.load(baseUrl + avatarPath)
.into(holder.avatar);
}
// set Name
holder.name.setText(videoList.get(position).getName());
// set duration
holder.videoDuration.setText( MetaDataHelper.getDuration(videoList.get(position).getDuration().longValue()));
// set age and view count
holder.videoMeta.setText(
MetaDataHelper.getMetaString(videoList.get(position).getCreatedAt(),
videoList.get(position).getViews(),
context
)
);
// set owner
holder.videoOwner.setText(
MetaDataHelper.getOwnerString(videoList.get(position).getAccount().getName(),
videoList.get(position).getAccount().getHost(),
context
)
);
holder.mView.setOnClickListener(v -> {
// Log.v("VideoAdapter", "click: " + videoList.get(position).getName());
Intent intent = new Intent(context,VideoPlayActivity.class);
intent.putExtra(EXTRA_VIDEOID, videoList.get(position).getUuid());
context.startActivity(intent);
});
holder.moreButton.setText(R.string.video_more_icon);
new Iconics.IconicsBuilder().ctx(context).on(holder.moreButton).build();
holder.moreButton.setOnClickListener(v -> {
PopupMenu popup = new PopupMenu(context, v);
popup.setOnMenuItemClickListener(menuItem -> {
switch (menuItem.getItemId()) {
case R.id.menu_share:
Intents.Share(context, videoList.get(position));
return true;
default:
return false;
}
});
popup.inflate(R.menu.menu_video_row_mode);
popup.show();
});
}
public void setData(ArrayList<Video> data) {
videoList.addAll(data);
this.notifyDataSetChanged();
}
public void clearData() {
videoList.clear();
this.notifyDataSetChanged();
}
@Override
public int getItemCount() {
return videoList.size();
}
class AccountViewHolder extends RecyclerView.ViewHolder {
TextView name, videoMeta, videoOwner, moreButton, videoDuration;
ImageView thumb, avatar;
View mView;
AccountViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.name);
thumb = itemView.findViewById(R.id.thumb);
avatar = itemView.findViewById(R.id.avatar);
videoMeta = itemView.findViewById(R.id.videoMeta);
videoOwner = itemView.findViewById(R.id.videoOwner);
moreButton = itemView.findViewById(R.id.moreButton);
videoDuration = itemView.findViewById(R.id.video_duration);
mView = itemView;
}
}
}

View File

@ -19,15 +19,14 @@ package net.schueller.peertube.adapter;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import android.content.pm.ActivityInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@ -35,6 +34,7 @@ import com.mikepenz.iconics.Iconics;
import com.squareup.picasso.Picasso;
import net.schueller.peertube.R;
import net.schueller.peertube.activity.AccountActivity;
import net.schueller.peertube.activity.VideoPlayActivity;
import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.MetaDataHelper;
@ -44,6 +44,7 @@ import net.schueller.peertube.model.Video;
import java.util.ArrayList;
import static net.schueller.peertube.activity.VideoListActivity.EXTRA_ACCOUNTDISPLAYNAME;
import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID;
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> {
@ -89,7 +90,7 @@ public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHol
holder.name.setText(videoList.get(position).getName());
// set duration
holder.videoDuration.setText( MetaDataHelper.getDuration(videoList.get(position).getDuration().longValue()));
holder.videoDuration.setText(MetaDataHelper.getDuration(videoList.get(position).getDuration().longValue()));
// set age and view count
holder.videoMeta.setText(
@ -100,18 +101,24 @@ public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHol
);
// set owner
holder.videoOwner.setText(
MetaDataHelper.getOwnerString(videoList.get(position).getAccount().getName(),
videoList.get(position).getAccount().getHost(),
context
)
String displayNameAndHost = MetaDataHelper.getOwnerString(videoList.get(position).getAccount().getName(),
videoList.get(position).getAccount().getHost(),
context
);
holder.videoOwner.setText(displayNameAndHost);
holder.videoOwner.setOnClickListener(v -> {
Intent intent = new Intent(context, AccountActivity.class);
intent.putExtra(EXTRA_ACCOUNTDISPLAYNAME, displayNameAndHost);
context.startActivity(intent);
});
holder.mView.setOnClickListener(v -> {
// Log.v("VideoAdapter", "click: " + videoList.get(position).getName());
Intent intent = new Intent(context,VideoPlayActivity.class);
Intent intent = new Intent(context, VideoPlayActivity.class);
intent.putExtra(EXTRA_VIDEOID, videoList.get(position).getUuid());
context.startActivity(intent);

View File

@ -0,0 +1,33 @@
/*
* 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;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
public class ChannelList {
@SerializedName("data")
private ArrayList<Channel> channelList;
public ArrayList<Channel> getChannelArrayList() {
return channelList;
}
}

View File

@ -1,11 +1,15 @@
package net.schueller.peertube.network;
import net.schueller.peertube.model.Account;
import net.schueller.peertube.model.Channel;
import net.schueller.peertube.model.ChannelList;
import net.schueller.peertube.model.Me;
import net.schueller.peertube.model.VideoList;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface GetUserService {
@ -20,4 +24,17 @@ public interface GetUserService {
@Query("sort") String sort
);
@GET("accounts/{displayName}")
Call<Account> getAccount(
@Path(value = "displayName", encoded = true) String displayName
);
@GET("accounts/{displayName}/video-channels")
Call<ChannelList> getAccountChannels(
@Path(value = "displayName", encoded = true) String displayName
);
}

View File

@ -71,4 +71,14 @@ public interface GetVideoDataService {
@Body RequestBody params
);
// https://troll.tv/api/v1/accounts/theouterlinux@peertube.mastodon.host/videos?start=0&count=8&sort=-publishedAt
@GET("accounts/{displayNameAndHost}/videos")
Call<VideoList> getAccountVideosData(
@Path(value = "displayNameAndHost", encoded = true) String displayNameAndHost,
@Query("start") int start,
@Query("count") int count,
@Query("sort") String sort
);
}

View File

@ -1,48 +1,209 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".activity.AccountActivity"
android:orientation="vertical">
tools:context="net.schueller.peertube.activity.AccountActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_user"
android:id="@+id/account_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tool_bar_user"
android:id="@+id/tool_bar_account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
android:elevation="4dp" />
android:elevation="4dp"
app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_marginBottom="0dp"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/account_about"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_above="@+id/account_navigation"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_below="@+id/account_appbar">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/account_username"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/account_about_account"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<Space
android:layout_width="12dp"
android:layout_height="1dp" />
<TextView
android:id="@+id/account_owner_string"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center|start"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/account_about_subscribers"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<Space
android:layout_width="12dp"
android:layout_height="1dp" />
<TextView
android:id="@+id/account_followers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center|start"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/account_about_description"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<Space
android:layout_width="12dp"
android:layout_height="1dp" />
<TextView
android:id="@+id/account_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center|start"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/account_about_joined"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<Space
android:layout_width="12dp"
android:layout_height="1dp" />
<TextView
android:id="@+id/account_joined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center|start"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/account_swipeRefreshLayout_videos"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/account_navigation"
android:layout_below="@+id/account_appbar"
android:layout_weight="1"
android:visibility="visible"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/account_video_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="" />
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/account_email"
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/account_swipeRefreshLayout_channels"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/account_navigation"
android:layout_below="@+id/account_appbar"
android:layout_weight="1"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/account_channel_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="" />
</LinearLayout>
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/account_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/menu_bottom_account" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,48 @@
<?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="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".activity.MeActivity"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_me"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tool_bar_me"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
android:elevation="4dp" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_marginBottom="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/account_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/account_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="" />
</LinearLayout>
</LinearLayout>

View File

@ -61,7 +61,7 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_gravity="bottom"
app:menu="@menu/menu_bottom"
app:menu="@menu/menu_bottom_video_list"
android:background="?android:attr/windowBackground"
/>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?><!-- START*** Root Container *** -->
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="0dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<ImageView
android:id="@+id/thumb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="@string/video_row_video_thumbnail"
android:maxHeight="300dp"
android:scaleType="fitXY" />
<TextView
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:layout_margin="2dp"
android:text=""
android:layout_above="@+id/avatar"
android:gravity="bottom|end"
android:layout_alignParentEnd="true"
android:id="@+id/video_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"/>
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_below="@+id/thumb"
android:layout_alignParentStart="true"
android:layout_marginTop="0dp"
android:contentDescription="@string/video_row_account_avatar"
android:paddingStart="12dp"
android:paddingTop="12dp"
android:paddingEnd="12dp" />
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/thumb"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
android:layout_toEndOf="@+id/avatar"
android:layout_marginEnd="24dp"
android:paddingTop="0dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/videoMeta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/name"
android:layout_marginStart="6dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="6dp"
android:layout_toEndOf="@+id/avatar"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
<TextView
android:id="@+id/videoOwner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/videoMeta"
android:layout_marginStart="6dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="6dp"
android:layout_toEndOf="@id/avatar"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
<TextView
android:id="@+id/moreButton"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_below="@+id/thumb"
android:layout_marginTop="16dp"
android:layout_marginStart="-16dp"
android:layout_marginEnd="0dp"
android:layout_toEndOf="@+id/name"
android:background="@null"
android:contentDescription="@string/descr_overflow_button"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?><!-- START*** Root Container *** -->
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="0dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<ImageView
android:id="@+id/thumb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="@string/video_row_video_thumbnail"
android:maxHeight="300dp"
android:scaleType="fitXY" />
<TextView
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:layout_margin="2dp"
android:text=""
android:layout_above="@+id/avatar"
android:gravity="bottom|end"
android:layout_alignParentEnd="true"
android:id="@+id/video_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"/>
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_below="@+id/thumb"
android:layout_alignParentStart="true"
android:layout_marginTop="0dp"
android:contentDescription="@string/video_row_account_avatar"
android:paddingStart="12dp"
android:paddingTop="12dp"
android:paddingEnd="12dp" />
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/thumb"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
android:layout_toEndOf="@+id/avatar"
android:layout_marginEnd="24dp"
android:paddingTop="0dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/videoMeta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/name"
android:layout_marginStart="6dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="6dp"
android:layout_toEndOf="@+id/avatar"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
<TextView
android:id="@+id/videoOwner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/videoMeta"
android:layout_marginStart="6dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="6dp"
android:layout_toEndOf="@id/avatar"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
<TextView
android:id="@+id/moreButton"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_below="@+id/thumb"
android:layout_marginTop="16dp"
android:layout_marginStart="-16dp"
android:layout_marginEnd="0dp"
android:layout_toEndOf="@+id/name"
android:background="@null"
android:contentDescription="@string/descr_overflow_button"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?><!-- START*** Root Container *** -->
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="0dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<ImageView
android:id="@+id/thumb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="@string/video_row_video_thumbnail"
android:maxHeight="300dp"
android:scaleType="fitXY" />
<TextView
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:layout_margin="2dp"
android:text=""
android:layout_above="@+id/avatar"
android:gravity="bottom|end"
android:layout_alignParentEnd="true"
android:id="@+id/video_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"/>
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_below="@+id/thumb"
android:layout_alignParentStart="true"
android:layout_marginTop="0dp"
android:contentDescription="@string/video_row_account_avatar"
android:paddingStart="12dp"
android:paddingTop="12dp"
android:paddingEnd="12dp" />
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/thumb"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
android:layout_toEndOf="@+id/avatar"
android:layout_marginEnd="24dp"
android:paddingTop="0dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/videoMeta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/name"
android:layout_marginStart="6dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="6dp"
android:layout_toEndOf="@+id/avatar"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
<TextView
android:id="@+id/videoOwner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/videoMeta"
android:layout_marginStart="6dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="6dp"
android:layout_toEndOf="@id/avatar"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
<TextView
android:id="@+id/moreButton"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_below="@+id/thumb"
android:layout_marginTop="16dp"
android:layout_marginStart="-16dp"
android:layout_marginEnd="0dp"
android:layout_toEndOf="@+id/name"
android:background="@null"
android:contentDescription="@string/descr_overflow_button"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/account_navigation_videos"
android:title="@string/account_bottom_menu_videos"
app:showAsAction="ifRoom|withText"/>
<item
android:id="@+id/account_navigation_channels"
android:title="@string/account_bottom_menu_channels"
app:showAsAction="always|withText"/>
<item
android:id="@+id/account_navigation_about"
android:title="@string/account_bottom_menu_about"
app:showAsAction="always|withText" />
</menu>

View File

@ -0,0 +1,335 @@
<resources>
<string name="app_name" translatable="false">PeerTube</string>
<string name="title_activity_video_play">İzleti Oynatma Etkinliği</string>
<string name="title_activity_settings">Ayarlar</string>
<string name="title_activity_login">Oturum aç</string>
<!-- Strings related to login -->
<string name="prompt_server">Sunucu</string>
<string name="prompt_email">E-posta / Kullanıcı adı</string>
<string name="prompt_password">Şifre</string>
<string name="action_sign_in">Oturum aç</string>
<string name="action_sign_in_short">Oturum aç</string>
<string name="error_invalid_email">Bu e-posta adresi geçersiz</string>
<string name="error_invalid_password">Bu şifre çok kısa</string>
<string name="error_incorrect_password">Bu şifre yanlış</string>
<string name="error_field_required">Bu alan gereklidir</string>
<string name="permission_rationale">"E-posta tanımlamaları için Rehber izinleri gerekir."
</string>
<!-- Action bar -->
<string name="action_bar_title_search">Arama</string>
<string name="action_bar_title_settings">Ayarlar</string>
<string name="action_bar_title_logout">Çıkış yap</string>
<!-- Bottom navigation bar -->
<string name="bottom_nav_title_home">Ev</string>
<string name="bottom_nav_title_trending">Eğilimler</string>
<string name="bottom_nav_title_subscriptions">Abonelikler</string>
<string name="bottom_nav_title_account">Hesap</string>
<!-- Strings related to Settings -->
<string name="peertube_required_server_version" translatable="false">1.0.0-alpha.7</string>
<string name="pref_default_api_base_url" formatted="false" translatable="false">https://troll.tv</string>
<string name="pref_title_peertube_server">PeerTube Sunucusu</string>
<!-- Strings related to Video meta data -->
<string name="meta_data_seperator" translatable="false">\u0020-\u0020</string>
<string name="meta_data_views">\u0020 Görüntüleme</string>
<string name="meta_data_owner_seperator" translatable="false">\@</string>
<string name="video_row_video_thumbnail">İzleti Küçük Resmi</string>
<string name="video_row_account_avatar">Hesap Resmi</string>
<string name="pref_title_show_nsfw">Ahlaksız İçerik</string>
<string name="pref_description_show_nsfw">Ahlaksız içeriği göster</string>
<string name="pref_language">Dil süzgeci</string>
<string name="pref_description_language">Gösterilmesi gereken izleti dillerini seçin. Hiçbiri seçili değilse tüm izletileri tüm dillerde gösterecek.</string>
<string name="title_activity_url_video_play">URL İzleti Oynatma Etkinliği</string>
<string name="pref_title_torrent_player">Torrent İzleti Oynatıcı</string>
<string name="pref_description_torrent_player">Bir torrent akışı üzerinden izleti oynatma. Bu Depolama İzinlerini gerektirir. (Deneyseldir, kararlı değil!)</string>
<string name="pref_title_license">Lisans</string>
<string name="pref_description_license">\n<b>GNU Affero Genel Kamu Lisansı v3.0</b>\n\nPBu en güçlü copyleft lisansının izinleri, aynı lisans altında lisanslı bir eser kullanan daha büyük işleri içeren lisanslı eserlerin ve değişikliklerin eksiksiz kaynak kodunu kullanıma sunmakla yükümlüdür. Telif hakkı ve lisans bildirimleri korunmalıdır. Katkıda bulunanlar açık bir patent hakkı verir. Bir ağ üzerinden hizmet sağlamak için değiştirilmiş bir sürüm kullanıldığında, değiştirilmiş sürümün kaynak kodunun tamamı kullanılabilir duruma getirilmelidir.</string>
<string name="pref_title_version">Sürüm</string>
<string name="search_hint">PeerTube\'da Ara</string>
<string name="title_activity_search">Arama</string>
<string name="no_data_available">Sonuç yok</string>
<string name="descr_overflow_button">Daha</string>
<string name="menu_share">Paylaş</string>
<string name="playback_channel_name" translatable="false">PeerTube</string>
<string name="invalid_url">Geçersiz bağlantı!</string>
<string name="pref_title_dark_mode">Karanlık Kipi</string>
<string name="pref_description_dark_mode">Karanlık kipin etkinleşmesi için uygulamayı yeniden başlatın.</string>
<string name="pref_title_app_theme">Uygulama Teması</string>
<string name="pref_description_app_theme">Temanın etkinleşmesi için uygulamayı yeniden başlatın.</string>
<string name="ab">Abhazca</string>
<string name="aa">Afar</string>
<string name="af">Afrikanca</string>
<string name="ak">Akan</string>
<string name="sq">Arnavutça</string>
<string name="ase">Amerikan İşaret Dili</string>
<string name="am">Amharca</string>
<string name="ar">Arapça</string>
<string name="an">Aragon</string>
<string name="hy">Ermenice</string>
<string name="as">Assamese</string>
<string name="av">Avarca</string>
<string name="ay">Aymara</string>
<string name="az">Azerice</string>
<string name="bm">Bambara</string>
<string name="ba">Başkurtca</string>
<string name="eu">Baskca</string>
<string name="be">Beyaz Rusça</string>
<string name="bn">Bengalce</string>
<string name="bi">Bislama Dili</string>
<string name="bs">Boşnakça</string>
<string name="bzs">Brezilya İşaret Dili</string>
<string name="br">Bretonca</string>
<string name="bfi">İngiliz İşaret Dili</string>
<string name="bg">Bulgarca</string>
<string name="my">Birmanyaca</string>
<string name="ca">Katalanca</string>
<string name="ch">Çemorro</string>
<string name="ce">Çeçence</string>
<string name="zh">Çince</string>
<string name="csl">Çin İşaret Dili</string>
<string name="cv">Çuvaşça</string>
<string name="kw">Kernevekçe</string>
<string name="co">Korsikaca</string>
<string name="cr">Krice</string>
<string name="hr">Hırvatça</string>
<string name="cs">Çekçe</string>
<string name="cse">Çek İşaret Dili</string>
<string name="da">Danimarkaca</string>
<string name="dsl">Danimarka İşaret Dili</string>
<string name="dv">Maldivce</string>
<string name="nl">Flemenkçe</string>
<string name="dz">Dzongka</string>
<string name="en">İngilizce</string>
<string name="eo">Esperanto</string>
<string name="et">Estonca</string>
<string name="ee">Ewe</string>
<string name="fo">Faroece</string>
<string name="fj">Fijice</string>
<string name="fi">Fince</string>
<string name="fr">Fransızca</string>
<string name="fsl">Fransız İşaret Dili</string>
<string name="ff">Pölce</string>
<string name="gl">Galiçyaca</string>
<string name="lg">Gandaca</string>
<string name="ka">Gürcüce</string>
<string name="de">Almanca</string>
<string name="gsg">Alman İşaret Dili</string>
<string name="gn">Guaranice</string>
<string name="gu">Guceratça</string>
<string name="ht">Haitice</string>
<string name="ha">Hausaca</string>
<string name="he">İbranice</string>
<string name="hz">Hereroca</string>
<string name="hi">Hintçe</string>
<string name="ho">Hiri Motu</string>
<string name="hu">Macarca</string>
<string name="is">İzlandaca</string>
<string name="ig">Igbo</string>
<string name="id">Endonezce</string>
<string name="iu">İnuitçe</string>
<string name="ik">İnyupikçe</string>
<string name="ga">İrlandaca</string>
<string name="it">Italyanca</string>
<string name="ja">Japonca</string>
<string name="jsl">Japon İşaret Dili</string>
<string name="jv">Cava Dili</string>
<string name="kl">Grönland Dili</string>
<string name="kn">Kannada Dili</string>
<string name="kr">Kanuri Dili</string>
<string name="ks">Keşmirce</string>
<string name="kk">Kazakça</string>
<string name="km">Kmerce</string>
<string name="ki">Kikuyu Dili</string>
<string name="rw">Ruandaca</string>
<string name="ky">Kırgızca</string>
<string name="tlh">Klingon Dili</string>
<string name="kv">Komice</string>
<string name="kg">Kongoca</string>
<string name="ko">Korece</string>
<string name="avk">Kotava Dili</string>
<string name="kj">Kuanyama Dili</string>
<string name="ku">Kürtçe</string>
<string name="lo">Laoca</string>
<string name="lv">Latonca</string>
<string name="li">Limburgca</string>
<string name="ln">Lingala Dili</string>
<string name="lt">Litvanca</string>
<string name="jbo">Kumanca</string>
<string name="lu">Luba-Katanga Dili</string>
<string name="lb">Lüksemburgca</string>
<string name="mk">Makedonca</string>
<string name="mg">Malgaşça</string>
<string name="ms">Malay Dili</string>
<string name="ml">Malayalamca</string>
<string name="mt">Maltaca</string>
<string name="gv">Man Dili</string>
<string name="mi">Maorice</string>
<string name="mr">Marathi</string>
<string name="mh">Marşalca</string>
<string name="el">Modern Yunanca (1453-)</string>
<string name="mn">Moğolca</string>
<string name="na">Nauruca</string>
<string name="nv">Navahoca</string>
<string name="ng">Ndonga Dili</string>
<string name="ne">Nepalce</string>
<string name="nd">Kuzey Ndebele Dili</string>
<string name="se">Kuzey Lapçaca</string>
<string name="no">Norveççe</string>
<string name="nb">Norveççe Kitap Dili</string>
<string name="nn">Yeni Norveççe</string>
<string name="ny">Çevaca</string>
<string name="oc">Oksitanca</string>
<string name="oj">Ojibvaca</string>
<string name="or">Oriya Dili</string>
<string name="om">Oromca</string>
<string name="os">Osetçe</string>
<string name="pks">Pakistan İşaret Dili</string>
<string name="pa">Pencapça</string>
<string name="fa">Farsça</string>
<string name="pl">Lehçe</string>
<string name="pt">Portekizce</string>
<string name="ps">Peştuca</string>
<string name="qu">Keçuvaca</string>
<string name="ro">Rumence</string>
<string name="rm">Romanşça</string>
<string name="rn">Rundice</string>
<string name="ru">Rusça</string>
<string name="rsl">Rus İşaret Dili</string>
<string name="sm">Samoaca</string>
<string name="sg">Sango Dili</string>
<string name="sc">Sarduca</string>
<string name="sdl">Suudi Arabistan İşaret Dili</string>
<string name="gd">İskoç Gal Dili</string>
<string name="sr">Sırpça</string>
<string name="sh">Sırp-Hırvatça</string>
<string name="sn">Shona</string>
<string name="ii">Sichuan Yi</string>
<string name="sd">Sintçe</string>
<string name="si">Seylanca</string>
<string name="sk">Slovakça</string>
<string name="sl">Slovence</string>
<string name="so">Somalice</string>
<string name="sfs">Güney Afrika İşaret Dili</string>
<string name="nr">Güney Ndebele</string>
<string name="st">Güney Sotho</string>
<string name="es">İspanyolca</string>
<string name="su">Sundaca</string>
<string name="sw">Svahili Dili</string>
<string name="ss">Svati Dili</string>
<string name="sv">İsveççe</string>
<string name="swl">İsveç İşaret Dili</string>
<string name="tl">Tagalogça</string>
<string name="ty">Tahiti Dili</string>
<string name="tg">Tacikçe</string>
<string name="ta">Tamilce</string>
<string name="tt">Tatarca</string>
<string name="te">Teluguca</string>
<string name="th">Tayca</string>
<string name="bo">Tibetçe</string>
<string name="ti">Tigrince</string>
<string name="to">Tonga (Tonga Adaları)</string>
<string name="ts">Tsongaca</string>
<string name="tn">Tsvana Dili</string>
<string name="tr">Türkçe</string>
<string name="tk">Turkmence</string>
<string name="tw">Twi</string>
<string name="ug">Uygurca</string>
<string name="uk">Ukraynaca</string>
<string name="ur">Urduca</string>
<string name="uz">Özbekçe</string>
<string name="ve">Venda Dili</string>
<string name="vi">Vietnamca</string>
<string name="wa">Valonca</string>
<string name="cy">Galce</string>
<string name="fy">Batı Frizcesi</string>
<string name="wo">Wolof Dili</string>
<string name="xh">Xhosa Dili</string>
<string name="yi">Yadişçe</string>
<string name="yo">Yorubaca</string>
<string name="za">Zhuangca</string>
<string name="zu">Zuluca</string>
<string name="red">Kırmızı</string>
<string name="pink">Pembe</string>
<string name="purple">Mor</string>
<string name="deeppurple">Koyu Mor</string>
<string name="indigo">Çivit</string>
<string name="blue">Mavi</string>
<string name="lightblue">ık Mavi</string>
<string name="cyan">Camgöbeği</string>
<string name="teal">Çamurcun</string>
<string name="green">Yeşil</string>
<string name="lightgreen">ık Yeşil</string>
<string name="lime">Misket Limonu</string>
<string name="yellow">Sarı</string>
<string name="amber">Kehribar</string>
<string name="orange">Turuncu</string>
<string name="deeporange">Koyu Turuncu</string>
<string name="brown">Kahverengi</string>
<string name="gray">Gri</string>
<string name="bluegray">Mavi gri</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_option_speed_icon" translatable="false">{faw-play-circle}</string>
<string name="video_option_quality_icon" translatable="false">{faw-cog}</string>
<string name="video_speed_active_icon" translatable="false">{faw-check}</string>
<string name="video_quality_active_icon" translatable="false">{faw-check}</string>
<string name="video_expand_icon" translatable="false">{faw-expand}</string>
<string name="video_compress_icon" translatable="false">{faw-compress}</string>
<string name="video_more_icon" translatable="false">{faw-ellipsis-v}</string>
<string name="video_thumbs_up_icon" translatable="false">{faw-thumbs-up}</string>
<string name="video_thumbs_down_icon" translatable="false">{faw-thumbs-down}</string>
<string name="video_share_icon" translatable="false">{faw-share}</string>
<string name="video_download_icon" translatable="false">{faw-download}</string>
<string name="video_save_icon" translatable="false">{faw-save}</string>
<string name="pref_title_background_play">Arkaplanda Oynatma</string>
<string name="pref_description_background_play">Etkinleştirilirse, arka planda izleti oynatmaya devam eder.</string>
<string name="bottom_nav_title_local">Yerel</string>
<string name="title_activity_account">Hesap</string>
<string name="menu_video_more_report">Rapor</string>
<string name="menu_video_more_blacklist">Karaliste</string>
<string name="video_download_permission_error">Yazma izni olmadan video indirilemiyor</string>
<string name="video_rating_failed">Değerlendirme Başarısız</string>
<string name="video_login_required_for_service">Bu hizmeti kullanmak için giriş yapmalısınız.</string>
<string name="video_meta_button_share">Paylaş</string>
<string name="video_meta_button_download">İndir</string>
<string name="video_meta_button_privacy">Gizlilik</string>
<string name="video_meta_button_category">Sınıf</string>
<string name="video_meta_button_license">Lisans</string>
<string name="video_meta_button_language">Dil</string>
<string name="video_meta_button_tags">Etiketler</string>
<string name="menu_video_options_playback_speed">Oynatma hızı</string>
<string name="menu_video_options_quality">Kalite</string>
<!-- Constants, Don't translate -->
<string name="pref_token_access" translatable="false">pref_token_access</string>
<string name="pref_token_refresh" translatable="false">pref_token_refresh</string>
<string name="pref_token_expiration" translatable="false">pref_token_expiration</string>
<string name="pref_token_type" translatable="false">pref_token_type</string>
<string name="pref_auth_username" translatable="false">pref_auth_username</string>
<string name="pref_auth_password" translatable="false">pref_auth_password</string>
<string name="video_rating_none" translatable="false">none</string>
<string name="video_rating_like" translatable="false">like</string>
<string name="video_rating_dislike" translatable="false">dislike</string>
</resources>

View File

@ -1,6 +1,5 @@
<?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>
@ -16,8 +15,8 @@
<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="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>

View File

@ -320,6 +320,17 @@
<string name="menu_video_options_playback_speed">Playback speed</string>
<string name="menu_video_options_quality">Quality</string>
<string name="account_bottom_menu_videos">Videos</string>
<string name="account_bottom_menu_channels">Channels</string>
<string name="account_bottom_menu_about">About</string>
<string name="account_about_account">Account:</string>
<string name="account_about_subscribers">Subscribers:</string>
<string name="account_about_description">Description:</string>
<string name="account_about_joined">Joined:</string>
<string name="api_error">Something went wrong, please try later!</string>
<!-- Constants, Don't translate -->
<string name="pref_token_access" translatable="false">pref_token_access</string>
<string name="pref_token_refresh" translatable="false">pref_token_refresh</string>
@ -332,5 +343,4 @@
<string name="video_rating_dislike" translatable="false">dislike</string>
</resources>

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.android.tools.build:gradle:3.3.0'
// NOTE: Do not place your application dependencies here; they belong

View File

@ -1,6 +1,6 @@
#Wed Nov 07 22:40:24 CET 2018
#Fri Jan 18 22:53:14 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip