Support recent - part 1

pull/21/head
FongMi 4 years ago
parent 392233ada0
commit 6ea5566903
  1. 26
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java
  2. 91
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
  3. 28
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
  4. 27
      app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java
  5. 74
      app/src/leanback/java/com/fongmi/android/tv/ui/presenter/HistoryPresenter.java
  6. 12
      app/src/leanback/java/com/fongmi/android/tv/ui/presenter/VodPresenter.java
  7. 14
      app/src/leanback/res/layout/adapter_vod.xml
  8. 2
      app/src/main/java/com/fongmi/android/tv/api/ApiConfig.java
  9. 91
      app/src/main/java/com/fongmi/android/tv/bean/History.java
  10. 9
      app/src/main/java/com/fongmi/android/tv/bean/Result.java
  11. 17
      app/src/main/java/com/fongmi/android/tv/bean/Vod.java
  12. 34
      app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
  13. 40
      app/src/main/java/com/fongmi/android/tv/db/dao/BaseDao.java
  14. 18
      app/src/main/java/com/fongmi/android/tv/db/dao/HistoryDao.java
  15. 30
      app/src/main/java/com/fongmi/android/tv/event/RefreshEvent.java
  16. 12
      app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java
  17. 3
      app/src/main/res/values-zh-rCN/strings.xml
  18. 3
      app/src/main/res/values-zh-rTW/strings.xml
  19. 3
      app/src/main/res/values/strings.xml

@ -19,12 +19,15 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.bean.History;
import com.fongmi.android.tv.bean.Vod;
import com.fongmi.android.tv.databinding.ActivityDetailBinding;
import com.fongmi.android.tv.databinding.ViewControllerBottomBinding;
import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.PlayerEvent;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.model.SiteViewModel;
import com.fongmi.android.tv.player.Players;
import com.fongmi.android.tv.ui.presenter.EpisodePresenter;
@ -55,6 +58,7 @@ public class DetailActivity extends BaseActivity implements KeyDown.Listener {
private SiteViewModel mSiteViewModel;
private boolean mFullscreen;
private KeyDown mKeyDown;
private History mHistory;
private View mOldView;
private int mCurrent;
@ -62,6 +66,10 @@ public class DetailActivity extends BaseActivity implements KeyDown.Listener {
return getIntent().getStringExtra("id");
}
private String getVodKey() {
return ApiConfig.get().getHome().getKey() + "_" + getVodFlag().getFlag() + "_" + getId();
}
private Vod.Flag getVodFlag() {
return (Vod.Flag) mFlagAdapter.get(mBinding.flag.getSelectedPosition());
}
@ -88,6 +96,7 @@ public class DetailActivity extends BaseActivity implements KeyDown.Listener {
@Override
protected void initView() {
mHistory = new History();
mKeyDown = KeyDown.create(this);
mFrameParams = mBinding.video.getLayoutParams();
mBinding.progressLayout.showProgress();
@ -166,6 +175,7 @@ public class DetailActivity extends BaseActivity implements KeyDown.Listener {
private void setDetail(Vod item) {
mBinding.progressLayout.showContent();
mBinding.video.setTag(item.getVodPic());
mBinding.name.setText(item.getVodName());
setText(mBinding.site, R.string.detail_site, ApiConfig.get().getHome().getName());
setText(mBinding.year, R.string.detail_year, item.getVodYear());
@ -219,7 +229,7 @@ public class DetailActivity extends BaseActivity implements KeyDown.Listener {
private void enterFullscreen() {
mBinding.video.setForeground(null);
mBinding.video.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
new Handler().postDelayed(() -> mBinding.video.setUseController(true),250);
new Handler().postDelayed(() -> mBinding.video.setUseController(true), 250);
mBinding.flag.setSelectedPosition(mCurrent);
mFullscreen = true;
}
@ -255,10 +265,22 @@ public class DetailActivity extends BaseActivity implements KeyDown.Listener {
Prefers.putScale(scale);
}
private void newHistory() {
mHistory.setKey(getVodKey());
mHistory.setEpisodeUrl(getEpisode().getUrl());
mHistory.setVodRemarks(getEpisode().getName());
mHistory.setCreateTime(System.currentTimeMillis());
mHistory.setVodPic(mBinding.video.getTag().toString());
mHistory.setVodName(mBinding.name.getText().toString());
AppDatabase.get().getHistoryDao().insertOrUpdate(mHistory);
EventBus.getDefault().post(RefreshEvent.recent());
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPlaybackStateChanged(PlayerEvent event) {
mBinding.progress.getRoot().setVisibility(event.getState() == Player.STATE_BUFFERING ? View.VISIBLE : View.GONE);
if (event.getState() == -1) Notify.show(R.string.error_play_parse);
if (event.getState() == Player.STATE_READY) newHistory();
}
@Override

@ -15,27 +15,38 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.bean.Func;
import com.fongmi.android.tv.bean.History;
import com.fongmi.android.tv.bean.Result;
import com.fongmi.android.tv.bean.Vod;
import com.fongmi.android.tv.databinding.ActivityHomeBinding;
import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.model.SiteViewModel;
import com.fongmi.android.tv.player.Players;
import com.fongmi.android.tv.server.Server;
import com.fongmi.android.tv.ui.custom.CustomRowPresenter;
import com.fongmi.android.tv.ui.custom.CustomSelector;
import com.fongmi.android.tv.ui.presenter.FuncPresenter;
import com.fongmi.android.tv.ui.presenter.HistoryPresenter;
import com.fongmi.android.tv.ui.presenter.ProgressPresenter;
import com.fongmi.android.tv.ui.presenter.TitlePresenter;
import com.fongmi.android.tv.ui.presenter.VodPresenter;
import com.fongmi.android.tv.utils.Clock;
import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.ResUtil;
import com.google.common.collect.Lists;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
public class HomeActivity extends BaseActivity implements VodPresenter.OnClickListener {
public class HomeActivity extends BaseActivity implements VodPresenter.OnClickListener, HistoryPresenter.OnClickListener {
private ActivityHomeBinding mBinding;
private SiteViewModel mSiteViewModel;
@ -61,11 +72,13 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
setRecyclerView();
setViewModel();
setAdapter();
getRecent();
getVideo();
}
@Override
protected void initEvent() {
EventBus.getDefault().register(this);
mFuncPresenter.setOnClickListener(this::onFuncClick);
mBinding.recycler.addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {
@Override
@ -81,6 +94,7 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
selector.addPresenter(String.class, new ProgressPresenter());
selector.addPresenter(ListRow.class, new CustomRowPresenter(16), VodPresenter.class);
selector.addPresenter(ListRow.class, new CustomRowPresenter(16), FuncPresenter.class);
selector.addPresenter(ListRow.class, new CustomRowPresenter(16), HistoryPresenter.class);
mBinding.recycler.setVerticalSpacing(ResUtil.dp2px(16));
mBinding.recycler.setAdapter(new ItemBridgeAdapter(mAdapter = new ArrayObjectAdapter(selector)));
}
@ -89,14 +103,7 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
mSiteViewModel = new ViewModelProvider(this).get(SiteViewModel.class);
mSiteViewModel.result.observe(this, result -> {
mAdapter.remove("progress");
if (result == null) return;
for (List<Vod> items : result.partition()) {
VodPresenter presenter = new VodPresenter(result.getColumns());
ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenter);
presenter.setOnClickListener(this);
adapter.addAll(0, items);
mAdapter.add(new ListRow(adapter));
}
if (result != null) addVideo(result);
});
}
@ -108,12 +115,23 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
}
private void getVideo() {
if (mAdapter.size() > 4) mAdapter.removeItems(4, mAdapter.size() - 4);
if (mAdapter.size() > getRecommendIndex()) mAdapter.removeItems(getRecommendIndex(), mAdapter.size() - getRecommendIndex());
if (ApiConfig.get().getHome().getKey().isEmpty()) return;
mSiteViewModel.homeContent();
mAdapter.add("progress");
}
private void addVideo(Result result) {
int columns = result.getList().size() % 6 == 0 ? 6 : 5;
List<ListRow> rows = new ArrayList<>();
for (List<Vod> items : Lists.partition(result.getList(), columns)) {
ArrayObjectAdapter adapter = new ArrayObjectAdapter(new VodPresenter(this, columns));
adapter.addAll(0, items);
rows.add(new ListRow(adapter));
}
mAdapter.addAll(mAdapter.size(), rows);
}
private ListRow getFuncRow() {
ArrayObjectAdapter adapter = new ArrayObjectAdapter(mFuncPresenter = new FuncPresenter());
adapter.add(Func.create(R.string.home_vod));
@ -124,6 +142,19 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
return new ListRow(adapter);
}
private void getRecent() {
int recentIndex = getRecentIndex();
int recommendIndex = getRecommendIndex();
if (recommendIndex - recentIndex == 2) mAdapter.removeItems(recentIndex, 1);
List<History> items = AppDatabase.get().getHistoryDao().getAll();
if (items.isEmpty()) return;
HistoryPresenter presenter = new HistoryPresenter(5);
ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenter);
presenter.setOnClickListener(this);
adapter.addAll(0, items);
mAdapter.add(recentIndex, new ListRow(adapter));
}
private void onFuncClick(Func item) {
switch (item.getResId()) {
case R.string.home_vod:
@ -135,18 +166,35 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
}
}
private int getRecentIndex() {
for (int i = 0; i < mAdapter.size(); i++) if (mAdapter.get(i).equals(R.string.home_recent)) return i + 1;
return -1;
}
private int getRecommendIndex() {
for (int i = 0; i < mAdapter.size(); i++) if (mAdapter.get(i).equals(R.string.home_recommend)) return i + 1;
return -1;
}
@Override
public void onItemClick(Vod item) {
DetailActivity.start(getActivity(), item.getVodId());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) return;
String type = data != null ? data.getStringExtra("type") : "";
if (type.equals("thumbnail")) mAdapter.notifyArrayItemRangeChanged(4, mAdapter.size() - 4);
else getVideo();
public void onItemClick(History item) {
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onAdapterChanged(RefreshEvent event) {
if (event.getType() == RefreshEvent.Type.VIDEO) {
getVideo();
} else if (event.getType() == RefreshEvent.Type.IMAGE) {
mAdapter.notifyArrayItemRangeChanged(getRecommendIndex(), mAdapter.size() - getRecommendIndex());
} else if (event.getType() == RefreshEvent.Type.RECENT) {
getRecent();
}
}
@Override
@ -162,10 +210,11 @@ public class HomeActivity extends BaseActivity implements VodPresenter.OnClickLi
@Override
protected void onDestroy() {
ApiConfig.get().release();
Players.get().release();
Clock.get().release();
Server.get().stop();
super.onDestroy();
Server.get().stop();
Clock.get().release();
Players.get().release();
ApiConfig.get().release();
EventBus.getDefault().unregister(this);
}
}

@ -20,24 +20,28 @@ import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.ItemBridgeAdapter;
import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.bean.Site;
import com.fongmi.android.tv.databinding.ActivitySettingBinding;
import com.fongmi.android.tv.databinding.DialogConfigBinding;
import com.fongmi.android.tv.databinding.DialogSiteBinding;
import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.net.Callback;
import com.fongmi.android.tv.ui.presenter.SitePresenter;
import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.Prefers;
import com.fongmi.android.tv.utils.ResUtil;
import org.greenrobot.eventbus.EventBus;
public class SettingActivity extends BaseActivity {
private ActivitySettingBinding mBinding;
public static void start(Activity activity) {
activity.startActivityForResult(new Intent(activity, SettingActivity.class), 1000);
activity.startActivity(new Intent(activity, SettingActivity.class));
}
private final ActivityResultLauncher<String> launcherString = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> loadConfig());
@ -67,9 +71,11 @@ public class SettingActivity extends BaseActivity {
bindingDialog.text.setText(Prefers.getUrl());
bindingDialog.text.setSelection(bindingDialog.text.getText().length());
AlertDialog dialog = Notify.show(this, bindingDialog.getRoot(), (dialogInterface, i) -> {
if (bindingDialog.text.getText().toString().equals(Prefers.getUrl())) return;
Prefers.putUrl(bindingDialog.text.getText().toString().trim());
mBinding.url.setText(Prefers.getUrl());
Notify.progress(this);
AppDatabase.clear();
checkUrl();
});
bindingDialog.text.setOnEditorActionListener((textView, actionId, event) -> {
@ -93,14 +99,16 @@ public class SettingActivity extends BaseActivity {
@Override
public void success() {
mBinding.home.setText(ApiConfig.get().getHome().getName());
setResult(RESULT_OK);
EventBus.getDefault().post(RefreshEvent.recent());
EventBus.getDefault().post(RefreshEvent.video());
Notify.dismiss();
}
@Override
public void error(int resId) {
mBinding.home.setText(ApiConfig.get().getHome().getName());
setResult(RESULT_OK);
EventBus.getDefault().post(RefreshEvent.recent());
EventBus.getDefault().post(RefreshEvent.video());
Notify.dismiss();
Notify.show(resId);
}
@ -122,11 +130,11 @@ public class SettingActivity extends BaseActivity {
}
public void setSite(ArrayObjectAdapter adapter, Site item) {
ApiConfig.get().setHome(item);
mBinding.home.setText(item.getName());
for (int i = 0; i < adapter.size(); i++) ((Site) adapter.get(i)).setHome(item);
adapter.notifyArrayItemRangeChanged(0, adapter.size());
mBinding.home.setText(item.getName());
ApiConfig.get().setHome(item);
setResult(RESULT_OK);
EventBus.getDefault().post(RefreshEvent.video());
Notify.dismiss();
}
@ -134,10 +142,8 @@ public class SettingActivity extends BaseActivity {
CharSequence[] array = ResUtil.getStringArray(R.array.select_thumbnail);
int index = Prefers.getThumbnail();
index = index == 2 ? 0 : ++index;
mBinding.compress.setText(array[index]);
Prefers.putThumbnail(index);
Intent intent = new Intent();
intent.putExtra("type", "thumbnail");
setResult(RESULT_OK, intent);
mBinding.compress.setText(array[index]);
EventBus.getDefault().post(RefreshEvent.image());
}
}

@ -15,19 +15,22 @@ import androidx.lifecycle.ViewModelProvider;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.bean.Filter;
import com.fongmi.android.tv.bean.Result;
import com.fongmi.android.tv.bean.Vod;
import com.fongmi.android.tv.databinding.FragmentVodBinding;
import com.fongmi.android.tv.model.SiteViewModel;
import com.fongmi.android.tv.ui.activity.DetailActivity;
import com.fongmi.android.tv.ui.custom.CustomRowPresenter;
import com.fongmi.android.tv.ui.custom.CustomSelector;
import com.fongmi.android.tv.ui.custom.CustomScroller;
import com.fongmi.android.tv.ui.custom.CustomSelector;
import com.fongmi.android.tv.ui.presenter.FilterPresenter;
import com.fongmi.android.tv.ui.presenter.ProgressPresenter;
import com.fongmi.android.tv.ui.presenter.VodPresenter;
import com.fongmi.android.tv.utils.ResUtil;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
@ -90,15 +93,8 @@ public class VodFragment extends Fragment implements CustomScroller.Callback, Vo
mSiteViewModel = new ViewModelProvider(this).get(SiteViewModel.class);
mSiteViewModel.result.observe(getViewLifecycleOwner(), result -> {
mAdapter.remove("progress");
if (result == null) return;
mScroller.endLoading(result.getList().isEmpty());
for (List<Vod> items : result.partition()) {
VodPresenter presenter = new VodPresenter(result.getColumns());
ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenter);
presenter.setOnClickListener(this);
adapter.addAll(0, items);
mAdapter.add(new ListRow(adapter));
}
mScroller.endLoading(result == null || result.getList().isEmpty());
if (result != null) addVideo(result);
});
}
@ -132,6 +128,17 @@ public class VodFragment extends Fragment implements CustomScroller.Callback, Vo
mAdapter.add("progress");
}
private void addVideo(Result result) {
int columns = result.getList().size() % 6 == 0 ? 6 : 5;
List<ListRow> rows = new ArrayList<>();
for (List<Vod> items : Lists.partition(result.getList(), columns)) {
ArrayObjectAdapter adapter = new ArrayObjectAdapter(new VodPresenter(this, columns));
adapter.addAll(0, items);
rows.add(new ListRow(adapter));
}
mAdapter.addAll(mAdapter.size(), rows);
}
@Override
public void onItemClick(Vod item) {
DetailActivity.start(getActivity(), item.getVodId());

@ -0,0 +1,74 @@
package com.fongmi.android.tv.ui.presenter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.leanback.widget.Presenter;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.bean.History;
import com.fongmi.android.tv.databinding.AdapterVodBinding;
import com.fongmi.android.tv.utils.ImgUtil;
import com.fongmi.android.tv.utils.ResUtil;
public class HistoryPresenter extends Presenter {
private OnClickListener mListener;
private int width, height;
public HistoryPresenter(int columns) {
setLayoutSize(columns);
}
public interface OnClickListener {
void onItemClick(History item);
}
public void setOnClickListener(OnClickListener listener) {
this.mListener = listener;
}
private void setLayoutSize(int columns) {
int space = ResUtil.dp2px(16) * (columns - 1) + ResUtil.dp2px(48);
int base = ResUtil.getScreenWidthPx() - space;
width = (int) base / columns;
height = (int) (width / 0.75);
}
@Override
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
ViewHolder holder = new ViewHolder(AdapterVodBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
holder.binding.getRoot().getLayoutParams().width = width;
holder.binding.getRoot().getLayoutParams().height = height;
return holder;
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object object) {
History item = (History) object;
ViewHolder holder = (ViewHolder) viewHolder;
holder.binding.name.setText(item.getVodName());
holder.binding.site.setVisibility(View.VISIBLE);
holder.binding.site.setText(ApiConfig.get().getSite(item.getSiteKey()).getName());
holder.binding.remark.setText(ResUtil.getString(R.string.vod_last, item.getVodRemarks()));
ImgUtil.load(item.getVodName(), item.getVodPic(), holder.binding.image);
setOnClickListener(holder, view -> mListener.onItemClick(item));
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
}
public static class ViewHolder extends Presenter.ViewHolder {
private final AdapterVodBinding binding;
public ViewHolder(@NonNull AdapterVodBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}

@ -8,14 +8,16 @@ import androidx.leanback.widget.Presenter;
import com.fongmi.android.tv.bean.Vod;
import com.fongmi.android.tv.databinding.AdapterVodBinding;
import com.fongmi.android.tv.utils.ImgUtil;
import com.fongmi.android.tv.utils.ResUtil;
public class VodPresenter extends Presenter {
private OnClickListener mListener;
private final OnClickListener mListener;
private int width, height;
public VodPresenter(int columns) {
public VodPresenter(OnClickListener listener, int columns) {
this.mListener = listener;
setLayoutSize(columns);
}
@ -23,10 +25,6 @@ public class VodPresenter extends Presenter {
void onItemClick(Vod item);
}
public void setOnClickListener(OnClickListener listener) {
this.mListener = listener;
}
private void setLayoutSize(int columns) {
int space = ResUtil.dp2px(16) * (columns - 1) + ResUtil.dp2px(48);
int base = ResUtil.getScreenWidthPx() - space;
@ -46,10 +44,10 @@ public class VodPresenter extends Presenter {
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object object) {
Vod item = (Vod) object;
ViewHolder holder = (ViewHolder) viewHolder;
item.loadImg(holder.binding.image);
holder.binding.name.setText(item.getVodName());
holder.binding.remark.setText(item.getVodRemarks());
holder.binding.remark.setVisibility(item.getRemarkVisible());
ImgUtil.load(item.getVodName(), item.getVodPic(), holder.binding.image);
setOnClickListener(holder, view -> mListener.onItemClick(item));
}

@ -14,6 +14,20 @@
android:scaleType="center"
tools:src="@drawable/ic_img_loading" />
<TextView
android:id="@+id/site"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="#CCF44336"
android:ellipsize="end"
android:padding="4dp"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="14sp"
android:visibility="gone"
tools:text="泥巴" />
<TextView
android:id="@+id/remark"
android:layout_width="wrap_content"

@ -84,7 +84,7 @@ public class ApiConfig {
try {
Response response = OKHttp.newCall(url).execute();
parseConfig(new Gson().fromJson(response.body().string(), JsonObject.class), callback);
} catch (IOException e) {
} catch (Exception e) {
handler.post(() -> callback.error(R.string.error_config_get));
}
}

@ -0,0 +1,91 @@
package com.fongmi.android.tv.bean;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity
public class History {
@NonNull
@PrimaryKey
private String key;
private String vodPic;
private String vodName;
private String vodRemarks;
private String episodeUrl;
private long createTime;
private long duration;
public History() {
}
@NonNull
public String getKey() {
return key;
}
public void setKey(@NonNull String key) {
this.key = key;
}
public String getVodPic() {
return vodPic;
}
public void setVodPic(String vodPic) {
this.vodPic = vodPic;
}
public String getVodName() {
return vodName;
}
public void setVodName(String vodName) {
this.vodName = vodName;
}
public String getVodRemarks() {
return vodRemarks;
}
public void setVodRemarks(String vodRemarks) {
this.vodRemarks = vodRemarks;
}
public String getEpisodeUrl() {
return episodeUrl;
}
public void setEpisodeUrl(String episodeUrl) {
this.episodeUrl = episodeUrl;
}
public long getCreateTime() {
return createTime;
}
public void setCreateTime(long createTime) {
this.createTime = createTime;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public String getSiteKey() {
return getKey().split("_")[0];
}
public String getFlag() {
return getKey().split("_")[1];
}
public String getVodId() {
return getKey().split("_")[2];
}
}

@ -2,7 +2,6 @@ package com.fongmi.android.tv.bean;
import androidx.annotation.NonNull;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
@ -81,14 +80,6 @@ public class Result {
return filters == null ? new LinkedHashMap<>() : filters;
}
public List<List<Vod>> partition() {
return Lists.partition(getList(), getColumns());
}
public int getColumns() {
return getList().size() % 6 == 0 ? 6 : 5;
}
@NonNull
@Override
public String toString() {

@ -2,14 +2,10 @@ package com.fongmi.android.tv.bean;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.utils.ImgUtil;
import com.fongmi.android.tv.utils.ResUtil;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
@ -77,10 +73,6 @@ public class Vod {
@ElementList(entry = "dd", required = false, inline = true)
private List<Flag> vodFlags;
public static Vod objectFrom(String str) {
return new Gson().fromJson(str, Vod.class);
}
public String getVodId() {
return TextUtils.isEmpty(vodId) ? "" : vodId;
}
@ -137,15 +129,6 @@ public class Vod {
return getVodRemarks().isEmpty() ? View.GONE : View.VISIBLE;
}
public void loadImg(ImageView view) {
if (TextUtils.isEmpty(getVodPic())) {
String text = getVodName().isEmpty() ? "" : getVodName().substring(0, 1);
view.setImageDrawable(TextDrawable.builder().buildRect(text, ColorGenerator.MATERIAL.getColor(text)));
} else {
ImgUtil.load(getVodPic(), view);
}
}
public void setVodFlags() {
String[] playFlags = getVodPlayFrom().split("\\$\\$\\$");
String[] playUrls = getVodPlayUrl().split("\\$\\$\\$");

@ -0,0 +1,34 @@
package com.fongmi.android.tv.db;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.bean.History;
import com.fongmi.android.tv.db.dao.HistoryDao;
@Database(entities = {History.class}, version = AppDatabase.VERSION, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public static final int VERSION = 1;
private static volatile AppDatabase instance;
public static synchronized AppDatabase get() {
if (instance == null) instance = create(App.get());
return instance;
}
private static AppDatabase create(Context context) {
return Room.databaseBuilder(context, AppDatabase.class, "tv").allowMainThreadQueries().fallbackToDestructiveMigration().build();
}
public abstract HistoryDao getHistoryDao();
public static void clear() {
get().getHistoryDao().delete();
}
}

@ -0,0 +1,40 @@
package com.fongmi.android.tv.db.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Transaction;
import androidx.room.Update;
import java.util.ArrayList;
import java.util.List;
@Dao
public abstract class BaseDao<T> {
@Insert(onConflict = OnConflictStrategy.IGNORE)
public abstract Long insert(T item);
@Insert(onConflict = OnConflictStrategy.IGNORE)
public abstract List<Long> insert(List<T> items);
@Update
public abstract void update(T item);
@Update
public abstract void update(List<T> items);
@Transaction
public void insertOrUpdate(T item) {
long id = insert(item);
if (id == -1) update(item);
}
@Transaction
public void insertOrUpdate(List<T> items) {
List<Long> result = insert(items);
List<T> list = new ArrayList<>();
for (int i = 0; i < result.size(); i++) if (result.get(i) == -1) list.add(items.get(i));
if (list.size() > 0) update(list);
}
}

@ -0,0 +1,18 @@
package com.fongmi.android.tv.db.dao;
import androidx.room.Dao;
import androidx.room.Query;
import com.fongmi.android.tv.bean.History;
import java.util.List;
@Dao
public abstract class HistoryDao extends BaseDao<History> {
@Query("SELECT * FROM history ORDER BY createTime DESC")
public abstract List<History> getAll();
@Query("DELETE FROM history")
public abstract void delete();
}

@ -0,0 +1,30 @@
package com.fongmi.android.tv.event;
public class RefreshEvent {
private final Type type;
public static RefreshEvent image() {
return new RefreshEvent(Type.IMAGE);
}
public static RefreshEvent video() {
return new RefreshEvent(Type.VIDEO);
}
public static RefreshEvent recent() {
return new RefreshEvent(Type.RECENT);
}
public RefreshEvent(Type type) {
this.type = type;
}
public Type getType() {
return type;
}
public enum Type {
IMAGE, VIDEO, RECENT
}
}

@ -1,10 +1,13 @@
package com.fongmi.android.tv.utils;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
@ -16,6 +19,15 @@ import com.fongmi.android.tv.R;
public class ImgUtil {
public static void load(String vodName, String vodPic, ImageView view) {
if (TextUtils.isEmpty(vodPic)) {
String text = vodName.isEmpty() ? "" : vodName.substring(0, 1);
view.setImageDrawable(TextDrawable.builder().buildRect(text, ColorGenerator.MATERIAL.getColor(text)));
} else {
ImgUtil.load(vodPic, view);
}
}
public static void load(String url, ImageView view) {
float thumbnail = 1 - Prefers.getThumbnail() * 0.3f;
Glide.with(App.get()).load(url).thumbnail(thumbnail).signature(new ObjectKey(url + "_" + thumbnail)).placeholder(R.drawable.ic_img_loading).error(R.drawable.ic_img_error).listener(getListener(view)).into(view);

@ -16,6 +16,9 @@
<string name="home_recent">最近观看</string>
<string name="home_recommend">更新推荐</string>
<!-- Vod -->
<string name="vod_last">上次看到<xliff:g name="name">%s</xliff:g></string>
<!-- Detail -->
<string name="detail_site">站源:<xliff:g name="name">%s</xliff:g></string>
<string name="detail_year">年份:<xliff:g name="name">%s</xliff:g></string>

@ -16,6 +16,9 @@
<string name="home_recent">最近觀看</string>
<string name="home_recommend">更新推薦</string>
<!-- Vod -->
<string name="vod_last">上次看到<xliff:g name="name">%s</xliff:g></string>
<!-- Detail -->
<string name="detail_site">站源:<xliff:g name="name">%s</xliff:g></string>
<string name="detail_year">年份:<xliff:g name="name">%s</xliff:g></string>

@ -16,6 +16,9 @@
<string name="home_recent">Recent</string>
<string name="home_recommend">Recommend</string>
<!-- Vod -->
<string name="vod_last">Last seen <xliff:g name="name">%s</xliff:g></string>
<!-- Detail -->
<string name="detail_site">Site: <xliff:g name="name">%s</xliff:g></string>
<string name="detail_year">Year: <xliff:g name="name">%s</xliff:g></string>

Loading…
Cancel
Save