add:直播间在线列表新增日榜、周榜

del:直播间在线列表移除守护列表
This commit is contained in:
zlzw 2022-08-20 14:15:44 +08:00
parent 2779fedc3b
commit a7b0ddec1d
15 changed files with 303 additions and 53 deletions

View File

@ -291,6 +291,13 @@ public class CommonRefreshView extends FrameLayout implements View.OnClickListen
mRecyclerView.addItemDecoration(itemDecoration);
}
/**
* 手动设置没有更多数据
* 因为日榜/周榜接口没有分页参数会导致一直读取重复数据
*/
public void setNotLoadMore(){
mSmartRefreshLayout.finishLoadMoreWithNoMoreData();
}
public void showLoading() {
mPageCount = 1;

View File

@ -7,6 +7,7 @@ package com.yunbao.common.http;
public class Data {
private int code;
private String msg;
private String data;//新增data字段兼容Contribute.index接口
private String[] info;
public int getCode() {
@ -32,4 +33,12 @@ public class Data {
public void setInfo(String[] info) {
this.info = info;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

View File

@ -45,7 +45,11 @@ public abstract class HttpCallback extends AbsCallback<JsonBean> {
//token过期重新登录
RouteUtil.forwardLoginInvalid(data.getMsg());
} else {
onSuccess(data.getCode(), data.getMsg(), data.getInfo());
if(data.getInfo().length==0){
onSuccess(data.getCode(), data.getMsg(), new String[]{data.getData()});
}else {
onSuccess(data.getCode(), data.getMsg(), data.getInfo());
}
}
} else {
L.e("服务器返回值异常--->ret: " + bean.getRet() + " msg: " + bean.getMsg());

View File

@ -358,6 +358,8 @@
<string name="live_push_failed_2">Microphone on failed</string>
<string name="live_onlookers">View</string>
<string name="live_online_list">Online List</string>
<string name="day_rank">DayRank</string>
<string name="week_rank">WeekRank</string>
<string name="live_audience">Viewers</string>
<string name="live_no_data">There is no anchor for the time being</string>
<string name="live_no_data_2">Let\'s start your live broadcast~</string>

View File

@ -574,6 +574,8 @@
<string name="delete">删除</string>
<string name="end">結束</string>
<string name="hot">熱門</string>
<string name="day_rank">日榜</string>
<string name="week_rank">周榜</string>
<string name="live_audience">觀衆</string>
<string name="rosy">红润</string>
<string name="skin">美白</string>

View File

@ -1,15 +1,19 @@
package com.yunbao.live.adapter;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.opensource.svgaplayer.SVGADrawable;
@ -20,17 +24,22 @@ import com.yunbao.common.CommonAppConfig;
import com.yunbao.common.Constants;
import com.yunbao.common.adapter.RefreshAdapter;
import com.yunbao.common.bean.LevelBean;
import com.yunbao.common.bean.UserBean;
import com.yunbao.common.glide.ImgLoader;
import com.yunbao.common.utils.CommonIconUtil;
import com.yunbao.common.utils.DpUtil;
import com.yunbao.common.utils.RandomUtil;
import com.yunbao.common.utils.ToastUtil;
import com.yunbao.live.R;
import com.yunbao.live.activity.LiveActivity;
import com.yunbao.live.bean.LiveUserGiftBean;
import com.yunbao.live.bean.LiveUserRankBean;
import com.yunbao.live.dialog.LiveUserMoreDialogFragment;
import java.net.MalformedURLException;
import java.net.URL;
public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
public class UserMoreInfoAdapter extends RefreshAdapter<UserBean> {
// private static final int HEAD = 1;
// private static final int NORMAL = 0;
@ -72,7 +81,6 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
// return NORMAL;
return position;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -83,8 +91,13 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder vh, int position) {
// vh.setIsRecyclable(false);
//type 34为日榜和周榜模式数据与观众有差距分开处理
if(Integer.parseInt(type)>3){
((Vh)vh).setRankModel(true);
}else{
((Vh)vh).setRankModel(false);
}
((Vh) vh).setData(mList.get(position), position);
}
@Override
@ -101,8 +114,12 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
ImageView mNoble;
ImageView mSex;
ImageView mLevel;
RelativeLayout mUserIcon;
LinearLayout mRanksIcon;
SVGAImageView gift_svga;
ImageView ivIcon;
ImageView rankImage;
TextView rankText;
public Vh(@NonNull View itemView) {
super(itemView);
title1 = (TextView)itemView.findViewById(R.id.title1);
@ -116,9 +133,13 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
mSex = (ImageView) itemView.findViewById(R.id.sex);
mLevel = (ImageView) itemView.findViewById(R.id.level);
gift_svga = (SVGAImageView)itemView.findViewById(R.id.gift_svga);
mUserIcon = (RelativeLayout)itemView.findViewById(R.id.userIcon);
mRanksIcon = (LinearLayout)itemView.findViewById(R.id.ranks);
rankImage=new ImageView(mContext);
rankText=new TextView(mContext);
}
void setData(final LiveUserGiftBean bean,int position) {
void setData(final UserBean bean,int position) {
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -144,11 +165,13 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
mIcon.setImageBitmap(null);
ivIcon.setVisibility(View.GONE);
tvName.setVisibility(View.GONE);
tvName.setTextSize(13);
tvName.setTextColor(mContext.getResources().getColor(R.color.white));
if(type.equals("1")) {
if (!bean.getDress().getMedal().equals("")) {
ImgLoader.display(mContext, bean.getDress().getMedal(), mIcon);
} else {
int guardType = bean.getGuardType();
int guardType = ((LiveUserGiftBean)bean).getGuardType();
if (guardType == Constants.GUARD_TYPE_NONE) {
if (mIcon.getVisibility() != View.VISIBLE) {
mIcon.setVisibility(View.INVISIBLE);
@ -167,7 +190,7 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
}
}
}else if(type.equals("2")){
int guardType = bean.getGuardType();
int guardType = ((LiveUserGiftBean)bean).getGuardType();
if (guardType == Constants.GUARD_TYPE_NONE) {
if (mIcon.getVisibility() != View.VISIBLE) {
mIcon.setVisibility(View.INVISIBLE);
@ -199,9 +222,31 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
}
});
}else if(type.equals("4")||type.equals("5")){//周榜
tvName.setVisibility(View.VISIBLE);
tvName.setText(((LiveUserRankBean)bean).getTotal()+"");
tvName.setTextColor(Color.parseColor("#9E9E9E"));
tvName.setTextSize(12);
switch (position){
case 0:rankImage.setImageResource(R.mipmap.day_list_no_1);break;
case 1:rankImage.setImageResource(R.mipmap.day_list_no_2);break;
case 2:rankImage.setImageResource(R.mipmap.day_list_no_3);break;
default:
rankText.setText((position+1)+"");
rankText.setTextColor(Color.parseColor("#FFFFFF"));
rankText.setTextSize(20);
rankText.setGravity(Gravity.CENTER);
}
mRanksIcon.removeAllViews();
if (position>2){
mRanksIcon.addView(rankText,0);
}else{
mRanksIcon.addView(rankImage,0);
}
}
ImgLoader.display(mContext, bean.getAvatar(), mAvatar);
if(bean.getDress().getAvatar_frame()!=null){
if(bean.getDress()!=null&&bean.getDress().getAvatar_frame()!=null){
gift_svga.setVisibility(View.VISIBLE);
if(bean.getDress().getAvatar_frame().contains("svga")) {
try {
new SVGAParser(mContext).parse(new URL(bean.getDress().getAvatar_frame()), new SVGAParser.ParseCompletion() {
@ -223,10 +268,12 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
ImgLoader.display(mContext,bean.getDress().getAvatar_frame(), gift_svga);
}
}else{
gift_svga.setVisibility(View.GONE);
}
mNoble.setVisibility(View.GONE);
if(bean.getDress().getMedal()!=null){
if(bean.getDress()!=null&&bean.getDress().getMedal()!=null){
ImgLoader.displayAvatar(mContext, bean.getDress().getMedal(), mNoble);
}else{
mNoble.setVisibility(View.GONE);
@ -238,6 +285,22 @@ public class UserMoreInfoAdapter extends RefreshAdapter<LiveUserGiftBean> {
ImgLoader.display(mContext, levelBean.getThumb(), mLevel);
}
}
/**
* 设置在榜单模式下头像的位置
* @param isRank 是否为榜单模式
*/
private void setRankModel(boolean isRank){
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mUserIcon.getLayoutParams();
if(isRank){
mRanksIcon.setVisibility(View.VISIBLE);
params.leftMargin= DpUtil.dp2px(16);
}else{
mRanksIcon.setVisibility(View.GONE);
params.leftMargin= DpUtil.dp2px(27);
}
mUserIcon.setLayoutParams(params);
}
}

View File

@ -0,0 +1,56 @@
package com.yunbao.live.bean;
import com.yunbao.common.bean.UserBean;
/**
* Created by zlzw on 2022/8/20.
* 直播间榜单实体类
*/
public class LiveUserRankBean extends UserBean {
private long total;
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
@Override
public String toString() {
return "LiveUserRankBean{" +
"id='" + id + '\'' +
", userNiceName='" + userNiceName + '\'' +
", avatar='" + avatar + '\'' +
", avatarThumb='" + avatarThumb + '\'' +
", sex=" + sex +
", signature='" + signature + '\'' +
", coin='" + coin + '\'' +
", gold='" + gold + '\'' +
", votes='" + votes + '\'' +
", consumption='" + consumption + '\'' +
", votestotal='" + votestotal + '\'' +
", province='" + province + '\'' +
", city='" + city + '\'' +
", location='" + location + '\'' +
", birthday='" + birthday + '\'' +
", level=" + level +
", levelAnchor=" + levelAnchor +
", lives=" + lives +
", follows=" + follows +
", fans=" + fans +
", vip=" + vip +
", liang=" + liang +
", car=" + car +
", medal_level=" + medal_level +
", medal_name='" + medal_name + '\'' +
", Dress=" + Dress +
", noble_id='" + noble_id + '\'' +
", yuanbao='" + yuanbao + '\'' +
", total=" + total +
'}';
}
}

View File

@ -11,12 +11,15 @@ import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yunbao.common.Constants;
import com.yunbao.common.adapter.RefreshAdapter;
import com.yunbao.common.bean.UserBean;
import com.yunbao.common.custom.CommonRefreshView;
import com.yunbao.common.dialog.AbsDialogFragment;
import com.yunbao.common.http.HttpCallback;
@ -26,8 +29,10 @@ import com.yunbao.live.activity.LiveActivity;
import com.yunbao.live.adapter.UserMoreInfoAdapter;
import com.yunbao.live.bean.LiveGuardInfo;
import com.yunbao.live.bean.LiveUserGiftBean;
import com.yunbao.live.bean.LiveUserRankBean;
import com.yunbao.live.http.LiveHttpUtil;
import java.util.ArrayList;
import java.util.List;
/**
@ -44,7 +49,8 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
public static LiveActivity activity = null;
public eightbitlab.com.blurview.BlurView blurView;
public TextView audience_btn, guard_btn, fans_btn, tags, btn, gz_view;
public TextView audience_btn, guard_btn, fans_btn, tags, btn, gz_view, dayRank, weekRank;
private RelativeLayout bottom_msg;//底部信息的布局在榜单列表下不需要显示底部信息
private String Tips = "1";
private String type = "guanzhong";
ImageView no_more;
@ -109,10 +115,13 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
mLiveUid = bundle.getString(Constants.LIVE_UID);
stream = bundle.getString(Constants.STREAM);
audience_btn = mRootView.findViewById(R.id.audience_btn);
bottom_msg = mRootView.findViewById(R.id.bottom_msg);
tags = mRootView.findViewById(R.id.tag);
no_more = mRootView.findViewById(R.id.no_more);
Tips = bundle.getString("By");
btn = mRootView.findViewById(R.id.btn);
dayRank = mRootView.findViewById(R.id.day_rank_btn);//日榜
weekRank = mRootView.findViewById(R.id.week_rank_btn);//周榜
gz_view = mRootView.findViewById(R.id.gz_view);
btn.setOnClickListener(new View.OnClickListener() {
@Override
@ -163,18 +172,29 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
no_more.setImageResource(R.mipmap.bixin);
}
});
dayRank.setOnClickListener(View->{
Tips="4";
Up();
type="dayRank";
mRefreshView.initData();
no_more.setImageBitmap(null);
});
weekRank.setOnClickListener(View->{
Tips="5";
Up();
type="weekRank";
mRefreshView.initData();
no_more.setImageBitmap(null);
});
mRefreshView = mRootView.findViewById(R.id.refreshView);
view_no = mRootView.findViewById(R.id.view_no);
userMoreInfoAdapter = new UserMoreInfoAdapter(mContext, LiveUserMoreDialogFragment.this);
Up();
mRefreshView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<LiveUserGiftBean>() {
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<UserBean>() {
@Override
public RefreshAdapter<LiveUserGiftBean> getAdapter() {
if (userMoreInfoAdapter == null) {
}
public RefreshAdapter<UserBean> getAdapter() {
userMoreInfoAdapter.notifyDataSetChanged();
return userMoreInfoAdapter;
}
@ -182,18 +202,53 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
@Override
public void loadData(int p, HttpCallback callback) {
Log.i("tag111", p + "ssss");
LiveHttpUtil.getUserList(mLiveUid, stream, type, p, callback);
pg = p;
if (p == 1) {
no_more.setVisibility(View.VISIBLE);
mRefreshView.setVisibility(View.GONE);
if(isRank()){
LiveHttpUtil.getUserRankList(mLiveUid,callback);
//榜单没有分页需求
mRefreshView.setPageCount(1);
}else {
LiveHttpUtil.getUserList(mLiveUid, stream, type, p, callback);
pg = p;
if (p == 1) {
no_more.setVisibility(View.VISIBLE);
mRefreshView.setVisibility(View.GONE);
}
}
}
@Override
public List processData(String[] info) {
JSONObject obj = JSON.parseObject(info[0]);
if(isRank()){
return processRankData(obj);
}else {
return processUserData(obj);
}
}
@Override
public List<LiveUserGiftBean> processData(String[] info) {
JSONObject obj = JSON.parseObject(info[0]);
List<LiveUserGiftBean> data = JSON.parseArray(obj.getString("userlist"), LiveUserGiftBean.class);
public void onRefreshSuccess(List<UserBean> list, int listCount) {
}
@Override
public void onRefreshFailure() {
}
@Override
public void onLoadMoreSuccess(List<UserBean> loadItemList, int loadItemCount) {
Log.i("tag333", "" + nums);
// userMoreInfoAdapter.num = nums;
// userMoreInfoAdapter.insertList(loadItemList);
}
@Override
public void onLoadMoreFailure() {
}
private List<LiveUserGiftBean> processUserData(JSONObject json){
List<LiveUserGiftBean> data = JSON.parseArray(json.getString("userlist"), LiveUserGiftBean.class);
Log.i("tag222", "ssss");
if (data.size() > 0 && pg == 1) {
nums = 0;
@ -213,26 +268,17 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
}
return data;
}
@Override
public void onRefreshSuccess(List<LiveUserGiftBean> list, int listCount) {
}
@Override
public void onRefreshFailure() {
}
@Override
public void onLoadMoreSuccess(List<LiveUserGiftBean> loadItemList, int loadItemCount) {
Log.i("tag333", "" + nums);
// userMoreInfoAdapter.num = nums;
// userMoreInfoAdapter.insertList(loadItemList);
}
@Override
public void onLoadMoreFailure() {
private List<LiveUserRankBean> processRankData(JSONObject json){
JSONArray rank=Integer.parseInt(Tips)==4?json.getJSONArray("list_day"):json.getJSONArray("list_week");
List<LiveUserRankBean> data =new ArrayList<>();
for (Object o : rank) {
JSONObject item= (JSONObject) o;
LiveUserRankBean bean=JSON.parseObject(item.getString("userinfo"),LiveUserRankBean.class);
bean.setTotal(item.getLong("total"));
data.add(bean);
}
mRefreshView.setNotLoadMore();
return data;
}
});
mRefreshView.initData();
@ -252,13 +298,12 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
}
void Up() {
bottom_msg.setVisibility(View.VISIBLE);
if (Tips.equals("1")) {
tags.setText("開通貴族,尊享超多特權!");
btn.setBackgroundResource(R.mipmap.btn_openvip);
btn.setText("開通貴族");
audience_btn.setTextColor(Color.parseColor("#fff6f7fb"));
guard_btn.setTextColor(Color.parseColor("#ff646464"));
fans_btn.setTextColor(Color.parseColor("#ff646464"));
setTextColor(audience_btn,guard_btn,fans_btn,weekRank,dayRank);
gz_view.setVisibility(View.GONE);
userMoreInfoAdapter.type = "1";
type = "guanzhong";
@ -266,9 +311,7 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
tags.setText("快為您喜歡的主播開通守護吧");
btn.setBackgroundResource(R.mipmap.btn_openprotection);
btn.setText("守護列表");
audience_btn.setTextColor(Color.parseColor("#ff646464"));
guard_btn.setTextColor(Color.parseColor("#fff6f7fb"));
fans_btn.setTextColor(Color.parseColor("#ff646464"));
setTextColor(guard_btn,audience_btn,fans_btn,dayRank,weekRank);
gz_view.setVisibility(View.GONE);
userMoreInfoAdapter.type = "2";
no_more.setImageResource(R.mipmap.grayicon);
@ -277,13 +320,36 @@ public class LiveUserMoreDialogFragment extends AbsDialogFragment implements Vie
tags.setText("快加入您喜歡的主播粉絲團吧");
btn.setText("加入粉絲團");
btn.setBackgroundResource(R.mipmap.btn_joinfans);
audience_btn.setTextColor(Color.parseColor("#ff646464"));
guard_btn.setTextColor(Color.parseColor("#ff646464"));
fans_btn.setTextColor(Color.parseColor("#fff6f7fb"));
setTextColor(fans_btn,audience_btn,guard_btn,dayRank,weekRank);
gz_view.setVisibility(View.GONE);
userMoreInfoAdapter.type = "3";
type = "fans";
no_more.setImageResource(R.mipmap.bixin);
}else if(Tips.equals("4")){
userMoreInfoAdapter.type = "4";
bottom_msg.setVisibility(View.GONE);
type="dayRank";
setTextColor(dayRank,audience_btn,guard_btn,fans_btn,gz_view,weekRank);
}else if (Tips.equals("5")){
userMoreInfoAdapter.type = "5";
bottom_msg.setVisibility(View.GONE);
type="weekRank";
setTextColor(weekRank,audience_btn,guard_btn,fans_btn,gz_view,dayRank);
}
}
/**
* 设置文本按钮颜色
* @param light 高亮的文本
* @param dark 暗淡的文本
*/
private void setTextColor(TextView light,TextView... dark){
light.setTextColor(Color.parseColor("#fff6f7fb"));
for (TextView textView : dark) {
textView.setTextColor(Color.parseColor("#ff646464"));
}
}
private boolean isRank(){
return Integer.parseInt(Tips)>3;
}
}

View File

@ -43,6 +43,17 @@ public class LiveHttpUtil {
.execute(callback);
}
/**
* 获取直播用户日榜/周榜
* @param liveUid 主播uid
* @param callback 回调
*/
public static void getUserRankList(String liveUid,HttpCallback callback){
HttpClient.getInstance().get("Contribute.index", LiveHttpConsts.GET_USER_LIST)
.params("uid", liveUid)
.execute(callback);
}
/**
* 获取当前直播间的连麦用户列表
*/

View File

@ -1222,7 +1222,7 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis
} else if (i == R.id.btn_prize_pool_level) {
((LiveActivity) mContext).openPrizePoolWindow();
} else if (i == R.id.user_more) {
((LiveActivity) mContext).openUserMoreListWindow(1);
((LiveActivity) mContext).openUserMoreListWindow(4);
} else if (i == R.id.hot_btn) {
((LiveActivity) mContext).openUserMoreListWindow(1);

View File

@ -31,6 +31,24 @@
android:layout_marginTop="20dp"
android:layout_marginBottom="24dp"
android:orientation="horizontal">
<TextView
android:id="@+id/day_rank_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/day_rank"
android:textColor="#fff6f7fb"
android:textSize="16sp" />
<TextView
android:id="@+id/week_rank_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/week_rank"
android:textColor="#fff6f7fb"
android:textSize="16sp" />
<TextView
android:id="@+id/audience_btn"
@ -48,6 +66,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:visibility="gone"
android:text="@string/live_guard"
android:textColor="#ff646464"
android:textSize="16sp" />
@ -96,6 +115,7 @@
</LinearLayout>
<RelativeLayout
android:id="@+id/bottom_msg"
android:layout_width="match_parent"
android:layout_height="65dp"
android:layout_alignParentBottom="true"

View File

@ -39,8 +39,18 @@
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/ranks"
android:layout_width="30dp"
android:layout_height="30dp"
android:gravity="center"
android:layout_gravity="center"
android:visibility="gone"
android:layout_marginLeft="16dp"
android:orientation="horizontal" />
<RelativeLayout
android:id="@+id/userIcon"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_marginLeft="27dp"

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB