Account details and account video list added

This commit is contained in:
Stefan Schueller 2019-01-06 15:22:14 +01:00 committed by Stefan Schüller
parent 1869cff5b0
commit a4864a71a8
20 changed files with 1248 additions and 132 deletions

View File

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

View File

@ -18,79 +18,138 @@
package net.schueller.peertube.activity; package net.schueller.peertube.activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.View;
import android.view.MenuItem;
import android.widget.TextView; 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.fontawesome_typeface_library.FontAwesome;
import com.mikepenz.iconics.IconicsDrawable; import com.mikepenz.iconics.IconicsDrawable;
import net.schueller.peertube.R; 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.helper.APIUrlHelper;
import net.schueller.peertube.model.Me; import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.model.OauthClient; import net.schueller.peertube.model.Account;
import net.schueller.peertube.model.Token; import net.schueller.peertube.model.ChannelList;
import net.schueller.peertube.network.AuthenticationService; import net.schueller.peertube.model.VideoList;
import net.schueller.peertube.network.GetUserService; import net.schueller.peertube.network.GetUserService;
import net.schueller.peertube.network.GetVideoDataService;
import net.schueller.peertube.network.RetrofitInstance; 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.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar; 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.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; 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 { 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 @Override
public boolean onCreateOptionsMenu(Menu menu) { protected void onCreate(Bundle savedInstanceState) {
MenuInflater inflater = getMenuInflater(); super.onCreate(savedInstanceState);
inflater.inflate(R.menu.menu_top_user, menu);
// Set an icon in the ActionBar setContentView(R.layout.activity_account);
menu.findItem(R.id.action_logout).setIcon(
new IconicsDrawable(this, FontAwesome.Icon.faw_sign_out_alt).actionBar());
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 swipeRefreshLayoutVideos.setOnRefreshListener(() -> {
public boolean onOptionsItemSelected(MenuItem item) { // Refresh items
if (!isLoadingVideos) {
videosCurrentStart = 0;
loadAccountVideos(displayNameAndHost);
}
});
switch (item.getItemId()) { // get video ID
// action with ID action_refresh was selected 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 @Override
@ -100,76 +159,178 @@ public class AccountActivity extends CommonActivity {
return false; return false;
} }
@Override private void loadAccount(String ownerString) {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account); // get video details from api
Call<Account> call = userService.getAccount(ownerString);
// Attaching the layout to the toolbar object call.enqueue(new Callback<Account>() {
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>() {
@Override @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()) { 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); // set view data
TextView email = findViewById(R.id.account_email); TextView ownerStringView = findViewById(R.id.account_owner_string);
ownerStringView.setText(owner);
username.setText(me.getUsername()); TextView followers = findViewById(R.id.account_followers);
email.setText(me.getEmail()); 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 @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 net.schueller.peertube.network.RetrofitInstance;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; 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 { public class LoginActivity extends CommonActivity {
private String TAG = "LoginActivity"; private String TAG = "LoginActivity";
@ -148,7 +144,7 @@ public class LoginActivity extends CommonActivity {
Log.wtf(TAG, "Logged in"); 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); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent); 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"; 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 VideoAdapter videoAdapter;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
@ -288,7 +289,7 @@ public class VideoListActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) {
Log.wtf("err", t.fillInStackTrace()); 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; isLoading = false;
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
} }
@ -427,7 +428,7 @@ public class VideoListActivity extends CommonActivity {
Intent intent = new Intent(this, LoginActivity.class); Intent intent = new Intent(this, LoginActivity.class);
this.startActivity(intent); this.startActivity(intent);
} else { } else {
Intent intent = new Intent(this, AccountActivity.class); Intent intent = new Intent(this, MeActivity.class);
this.startActivity(intent); 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.Context;
import android.content.Intent; 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;
import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -35,6 +34,7 @@ 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.activity.AccountActivity;
import net.schueller.peertube.activity.VideoPlayActivity; import net.schueller.peertube.activity.VideoPlayActivity;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.MetaDataHelper; import net.schueller.peertube.helper.MetaDataHelper;
@ -44,6 +44,7 @@ import net.schueller.peertube.model.Video;
import java.util.ArrayList; import java.util.ArrayList;
import static net.schueller.peertube.activity.VideoListActivity.EXTRA_ACCOUNTDISPLAYNAME;
import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID; import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID;
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> { 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()); holder.name.setText(videoList.get(position).getName());
// set duration // 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 // set age and view count
holder.videoMeta.setText( holder.videoMeta.setText(
@ -100,18 +101,24 @@ public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHol
); );
// set owner // set owner
holder.videoOwner.setText( String displayNameAndHost = MetaDataHelper.getOwnerString(videoList.get(position).getAccount().getName(),
MetaDataHelper.getOwnerString(videoList.get(position).getAccount().getName(), videoList.get(position).getAccount().getHost(),
videoList.get(position).getAccount().getHost(), context
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 -> { holder.mView.setOnClickListener(v -> {
// Log.v("VideoAdapter", "click: " + videoList.get(position).getName()); // 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()); intent.putExtra(EXTRA_VIDEOID, videoList.get(position).getUuid());
context.startActivity(intent); 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; 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.Me;
import net.schueller.peertube.model.VideoList; import net.schueller.peertube.model.VideoList;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.http.GET; import retrofit2.http.GET;
import retrofit2.http.Header; import retrofit2.http.Header;
import retrofit2.http.Path;
import retrofit2.http.Query; import retrofit2.http.Query;
public interface GetUserService { public interface GetUserService {
@ -20,4 +24,17 @@ public interface GetUserService {
@Query("sort") String sort @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 @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"?> <?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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" tools:context="net.schueller.peertube.activity.AccountActivity">
tools:context=".activity.AccountActivity"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_user" android:id="@+id/account_appbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" <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_width="match_parent"
android:layout_height="wrap_content" 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> </com.google.android.material.appbar.AppBarLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/account_about"
<LinearLayout
android:layout_marginBottom="0dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" 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 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/account_username" 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:text="" />
<androidx.appcompat.widget.AppCompatTextView </androidx.recyclerview.widget.RecyclerView>
android:id="@+id/account_email"
</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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:text="" />
</LinearLayout> </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_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:layout_gravity="bottom" android:layout_gravity="bottom"
app:menu="@menu/menu_bottom" app:menu="@menu/menu_bottom_video_list"
android:background="?android:attr/windowBackground" 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

@ -320,6 +320,17 @@
<string name="menu_video_options_playback_speed">Playback speed</string> <string name="menu_video_options_playback_speed">Playback speed</string>
<string name="menu_video_options_quality">Quality</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 --> <!-- Constants, Don't translate -->
<string name="pref_token_access" translatable="false">pref_token_access</string> <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_refresh" translatable="false">pref_token_refresh</string>
@ -332,5 +343,4 @@
<string name="video_rating_dislike" translatable="false">dislike</string> <string name="video_rating_dislike" translatable="false">dislike</string>
</resources> </resources>