From bccf9d005c091f8ee82f0e426ab421419e1cb117 Mon Sep 17 00:00:00 2001 From: FongMi Date: Sun, 30 Oct 2022 00:49:14 +0800 Subject: [PATCH] Support pass --- .../fongmi/android/tv/impl/PassCallback.java | 6 ++ .../android/tv/ui/activity/LiveActivity.java | 42 ++++++++- .../tv/ui/custom/dialog/PassDialog.java | 94 +++++++++++++++++++ .../tv/ui/presenter/GroupPresenter.java | 1 - app/src/leanback/res/layout/dialog_pass.xml | 40 ++++++++ .../com/fongmi/android/tv/api/LiveConfig.java | 15 ++- .../com/fongmi/android/tv/bean/Group.java | 23 ++--- app/src/main/res/values-zh-rCN/strings.xml | 5 +- app/src/main/res/values-zh-rTW/strings.xml | 5 +- app/src/main/res/values/strings.xml | 5 +- 10 files changed, 206 insertions(+), 30 deletions(-) create mode 100644 app/src/leanback/java/com/fongmi/android/tv/impl/PassCallback.java create mode 100644 app/src/leanback/java/com/fongmi/android/tv/ui/custom/dialog/PassDialog.java create mode 100644 app/src/leanback/res/layout/dialog_pass.xml diff --git a/app/src/leanback/java/com/fongmi/android/tv/impl/PassCallback.java b/app/src/leanback/java/com/fongmi/android/tv/impl/PassCallback.java new file mode 100644 index 000000000..c3d81619a --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/impl/PassCallback.java @@ -0,0 +1,6 @@ +package com.fongmi.android.tv.impl; + +public interface PassCallback { + + void setPass(String pass); +} diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index 0363babbf..ed9a8fcbd 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -16,20 +16,24 @@ import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.RecyclerView; import androidx.viewbinding.ViewBinding; +import com.fongmi.android.tv.R; import com.fongmi.android.tv.api.LiveConfig; import com.fongmi.android.tv.bean.Channel; import com.fongmi.android.tv.bean.Group; import com.fongmi.android.tv.databinding.ActivityLiveBinding; import com.fongmi.android.tv.event.PlayerEvent; +import com.fongmi.android.tv.impl.PassCallback; import com.fongmi.android.tv.model.LiveViewModel; import com.fongmi.android.tv.player.Players; import com.fongmi.android.tv.player.source.Force; import com.fongmi.android.tv.ui.custom.CustomKeyDownLive; import com.fongmi.android.tv.ui.custom.CustomLiveListView; +import com.fongmi.android.tv.ui.custom.dialog.PassDialog; import com.fongmi.android.tv.ui.presenter.ChannelPresenter; import com.fongmi.android.tv.ui.presenter.GroupPresenter; import com.fongmi.android.tv.utils.Clock; import com.fongmi.android.tv.utils.Prefers; +import com.fongmi.android.tv.utils.ResUtil; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ui.StyledPlayerView; @@ -40,13 +44,14 @@ import org.greenrobot.eventbus.ThreadMode; import java.util.ArrayList; import java.util.List; -public class LiveActivity extends BaseActivity implements GroupPresenter.OnClickListener, ChannelPresenter.OnClickListener, CustomKeyDownLive.Listener, CustomLiveListView.Callback { +public class LiveActivity extends BaseActivity implements GroupPresenter.OnClickListener, ChannelPresenter.OnClickListener, CustomKeyDownLive.Listener, CustomLiveListView.Callback, PassCallback { private ActivityLiveBinding mBinding; private ArrayObjectAdapter mChannelAdapter; private ArrayObjectAdapter mGroupAdapter; private CustomKeyDownLive mKeyDown; private LiveViewModel mViewModel; + private List mHides; private Handler mHandler; private Players mPlayers; private Channel mChannel; @@ -55,6 +60,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick private Runnable mR0; private Runnable mR1; private Runnable mR2; + private int count; public static void start(Activity activity) { if (LiveConfig.get().isEmpty()) return; @@ -86,6 +92,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick mPlayers = new Players().init(); mHandler = new Handler(Looper.getMainLooper()); mKeyDown = CustomKeyDownLive.create(this); + mHides = new ArrayList<>(); setRecyclerView(); setViewModel(); setVideoView(); @@ -126,13 +133,16 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick private void getLive() { List items = new ArrayList<>(); - items.addAll(LiveConfig.get().getHome().getGroups()); + items.add(new Group(ResUtil.getString(R.string.live_keep))); + for (Group group : LiveConfig.get().getHome().getGroups()) (group.isHidden() ? mHides : items).add(group); + items.add(new Group(ResUtil.getString(R.string.live_setting))); mGroupAdapter.setItems(items, null); mBinding.group.setVisibility(mGroupAdapter.size() == 1 ? View.GONE : View.VISIBLE); - setPosition(LiveConfig.get().getKeep()); + setPosition(LiveConfig.get().getKeep(mGroupAdapter.unmodifiableList())); } private void setPosition(int[] position) { + if (position[0] == -1) return; mGroup = (Group) mGroupAdapter.get(position[0]); mBinding.group.setSelectedPosition(position[0]); mGroup.setPosition(position[1]); @@ -192,10 +202,18 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick mBinding.info.getRoot().setVisibility(View.VISIBLE); } + private void resetPass() { + this.count = 0; + } + @Override public void onItemClick(Group item) { mChannelAdapter.setItems(mGroup.getChannel(), null); mBinding.channel.setSelectedPosition(mGroup.getPosition()); + if (!item.isKeep() || ++count < 5) return; + mHandler.removeCallbacks(mR0); + PassDialog.show(this); + resetPass(); } @Override @@ -225,6 +243,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick mBinding.group.setSelectedPosition(position); mChannelAdapter.setItems(mGroup.getChannel(), null); mGroup.setPosition(0); + resetPass(); } @Override @@ -235,6 +254,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick mBinding.group.setSelectedPosition(position); mChannelAdapter.setItems(mGroup.getChannel(), null); mGroup.setPosition(mGroup.getChannel().size() - 1); + resetPass(); } @Override @@ -258,8 +278,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick @Override public void onFind(String number) { mBinding.digital.setVisibility(View.GONE); - int[] position = LiveConfig.get().find(number); - if (position[0] != -1) setPosition(position); + setPosition(LiveConfig.get().find(number, mGroupAdapter.unmodifiableList())); } @Override @@ -304,6 +323,19 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick public void onLongPress() { } + @Override + public void setPass(String pass) { + int position = mGroupAdapter.size() - 1; + for (Group item : mHides) { + if (!item.getPass().equals(pass)) continue; + mGroupAdapter.add(position, item); + mBinding.group.setSelectedPosition(position); + mHides.remove(item); + onItemClick(item); + break; + } + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onPlayerEvent(PlayerEvent event) { switch (event.getState()) { diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/dialog/PassDialog.java b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/dialog/PassDialog.java new file mode 100644 index 000000000..ba4c0b3b7 --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/dialog/PassDialog.java @@ -0,0 +1,94 @@ +package com.fongmi.android.tv.ui.custom.dialog; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; + +import com.fongmi.android.tv.databinding.DialogPassBinding; +import com.fongmi.android.tv.impl.PassCallback; +import com.fongmi.android.tv.utils.ResUtil; +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.BottomSheetDialog; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +public class PassDialog extends BottomSheetDialogFragment { + + private final PassCallback callback; + private DialogPassBinding binding; + + public static void show(FragmentActivity activity) { + for (Fragment fragment : activity.getSupportFragmentManager().getFragments()) if (fragment instanceof BottomSheetDialogFragment) return; + new PassDialog(activity).show(activity.getSupportFragmentManager(), null); + } + + private PassDialog(FragmentActivity activity) { + this.callback = (PassCallback) activity; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + binding = DialogPassBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState); + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setOnShowListener((DialogInterface f) -> setBehavior(dialog)); + return dialog; + } + + private void setBehavior(BottomSheetDialog dialog) { + WindowManager.LayoutParams params = dialog.getWindow().getAttributes(); + FrameLayout bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet); + BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); + behavior.setState(BottomSheetBehavior.STATE_EXPANDED); + params.width = ResUtil.dp2px(250); + dialog.getWindow().setAttributes(params); + behavior.setSkipCollapsed(true); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initEvent(); + } + + protected void initEvent() { + binding.positive.setOnClickListener(this::onPass); + binding.pass.setOnEditorActionListener(this::onEditorAction); + } + + private boolean onEditorAction(TextView view, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) binding.positive.performClick(); + return true; + } + + private void onPass(View view) { + String pass = binding.pass.getText().toString().trim(); + if (pass.length() > 0) callback.setPass(pass); + dismiss(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/GroupPresenter.java b/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/GroupPresenter.java index 4b1d75a0c..97468377c 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/GroupPresenter.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/presenter/GroupPresenter.java @@ -33,7 +33,6 @@ public class GroupPresenter extends Presenter { item.loadLogo(holder.binding.logo); holder.binding.name.setText(item.getName()); holder.binding.logo.setVisibility(item.getVisible()); - holder.binding.getRoot().setSelected(item.isSelected()); setOnClickListener(holder, view -> mListener.onItemClick(item)); } diff --git a/app/src/leanback/res/layout/dialog_pass.xml b/app/src/leanback/res/layout/dialog_pass.xml new file mode 100644 index 000000000..c6340e08c --- /dev/null +++ b/app/src/leanback/res/layout/dialog_pass.xml @@ -0,0 +1,40 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java b/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java index f9e253fb5..372c4274b 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java +++ b/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java @@ -131,24 +131,23 @@ public class LiveConfig { } public void setKeep(Group group, Channel channel) { - Prefers.putKeep(home.getName() + AppDatabase.SYMBOL + group.getName() + AppDatabase.SYMBOL + channel.getName()); + if (!group.isHidden()) Prefers.putKeep(home.getName() + AppDatabase.SYMBOL + group.getName() + AppDatabase.SYMBOL + channel.getName()); } - public int[] getKeep() { + public int[] getKeep(List items) { String[] splits = Prefers.getKeep().split(AppDatabase.SYMBOL); - if (!home.getName().equals(splits[0])) return new int[]{0, 0}; - for (int i = 0; i < home.getGroups().size(); i++) { - Group group = home.getGroups().get(i); + if (!home.getName().equals(splits[0])) return new int[]{1, 0}; + for (int i = 0; i < items.size(); i++) { + Group group = items.get(i); if (group.getName().equals(splits[1])) { int j = group.find(splits[2]); if (j != -1) return new int[]{i, j}; } } - return new int[]{0, 0}; + return new int[]{1, 0}; } - public int[] find(String number) { - List items = home.getGroups(); + public int[] find(String number, List items) { for (int i = 0; i < items.size(); i++) { int j = items.get(i).find(Integer.parseInt(number)); if (j != -1) return new int[]{i, j}; diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Group.java b/app/src/main/java/com/fongmi/android/tv/bean/Group.java index b1eea9546..6f917bd3d 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Group.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Group.java @@ -6,6 +6,8 @@ import android.widget.ImageView; import com.bumptech.glide.Glide; import com.fongmi.android.tv.App; +import com.fongmi.android.tv.R; +import com.fongmi.android.tv.utils.ResUtil; import com.google.gson.annotations.SerializedName; import java.util.ArrayList; @@ -22,7 +24,6 @@ public class Group { @SerializedName("pass") private String pass; - private boolean selected; private int position; public Group(String name) { @@ -64,18 +65,6 @@ public class Group { this.pass = pass; } - public boolean isSelected() { - return selected; - } - - public void setSelected(boolean selected) { - this.selected = selected; - } - - public void setSelected(Group item) { - this.selected = item.equals(this); - } - public int getPosition() { return position; } @@ -88,6 +77,14 @@ public class Group { return !TextUtils.isEmpty(getPass()); } + public boolean isKeep() { + return getName().equals(ResUtil.getString(R.string.live_keep)); + } + + public boolean isSetting() { + return getName().equals(ResUtil.getString(R.string.live_setting)); + } + public int getVisible() { return getLogo().isEmpty() ? View.GONE : View.VISIBLE; } diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 03a295b80..be6c5c81a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -11,9 +11,12 @@ 上次看到%s + 收藏 + 密码 + 设定 + 暂无节目资讯 正在播放:%s/%s 下个节目:%s/%s - 暂无节目资讯 线路 %s/%s diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 4784703cf..7ac361421 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -11,9 +11,12 @@ 上次看到%s + 收藏 + 密碼 + 設定 + 暫無頻道資訊 正在播放:%s/%s 下個節目:%s/%s - 暫無頻道資訊 來源 %s/%s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0b6e67265..0e7cdfbdf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,9 +11,12 @@ Last seen %s + Keep + Pass + Setting + No schedule Playing: %s/%s Nex: %s/%s - No schedule Line %s/%s