diff --git a/app/src/main/java/com/fongmi/android/tv/event/ActionEvent.java b/app/src/main/java/com/fongmi/android/tv/event/ActionEvent.java index 9c866c3d0..21709f7a8 100644 --- a/app/src/main/java/com/fongmi/android/tv/event/ActionEvent.java +++ b/app/src/main/java/com/fongmi/android/tv/event/ActionEvent.java @@ -27,6 +27,10 @@ public class ActionEvent { send(NEXT); } + public static void pause() { + send(PAUSE); + } + public ActionEvent(String action) { this.action = action; } diff --git a/app/src/main/java/com/fongmi/android/tv/player/Timer.java b/app/src/main/java/com/fongmi/android/tv/player/Timer.java new file mode 100644 index 000000000..98acf0c8b --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/player/Timer.java @@ -0,0 +1,81 @@ +package com.fongmi.android.tv.player; + +import android.os.CountDownTimer; + +import com.fongmi.android.tv.event.ActionEvent; + +import java.util.concurrent.TimeUnit; + +public class Timer { + + private CountDownTimer timer; + private Callback callback; + private long tick; + + private static class Loader { + static volatile Timer INSTANCE = new Timer(); + } + + public static Timer get() { + return Loader.INSTANCE; + } + + public boolean isRunning() { + return timer != null; + } + + public void setCallback(Callback callback) { + this.callback = callback; + } + + public long getTick() { + return tick; + } + + public void set(long t) { + timer = new CountDownTimer(t, 1000) { + @Override + public void onTick(long tick) { + Timer.this.onTick(tick); + } + + @Override + public void onFinish() { + Timer.this.onFinish(); + } + }.start(); + } + + private void onTick(long tick) { + this.tick = tick; + if (callback != null) callback.onTick(tick); + } + + private void onFinish() { + if (callback != null) callback.onFinish(); + ActionEvent.pause(); + reset(); + } + + public void delay() { + cancel(); + set(TimeUnit.MINUTES.toMillis(5) + tick); + } + + public void reset() { + tick = 0; + cancel(); + } + + public void cancel() { + if (timer != null) timer.cancel(); + timer = null; + } + + public interface Callback { + + void onTick(long tick); + + void onFinish(); + } +} diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 61b69cb51..9e774d5fc 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -65,6 +65,7 @@ import com.fongmi.android.tv.model.SiteViewModel; import com.fongmi.android.tv.player.ExoUtil; import com.fongmi.android.tv.player.Players; import com.fongmi.android.tv.player.Source; +import com.fongmi.android.tv.player.Timer; import com.fongmi.android.tv.player.danmu.Parser; import com.fongmi.android.tv.service.PlaybackService; import com.fongmi.android.tv.ui.adapter.EpisodeAdapter; @@ -762,7 +763,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } private void onSetting() { - mControlDialog = ControlDialog.create().parent(mBinding).history(mHistory).players(mPlayers).parse(isUseParse()).show(this); + mControlDialog = ControlDialog.create().parent(mBinding).history(mHistory).player(mPlayers).parse(isUseParse()).show(this); } private void onLock() { @@ -1690,6 +1691,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo stopSearch(); mClock.release(); mPlayers.release(); + Timer.get().reset(); Source.get().stop(); RefreshEvent.history(); App.removeCallbacks(mR1, mR2, mR3, mR4); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/ControlDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/ControlDialog.java index 39cfd9063..eb5f7c187 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/ControlDialog.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/ControlDialog.java @@ -32,11 +32,12 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis private DialogControlBinding binding; private ActivityVideoBinding parent; + private FragmentActivity activity; private List scales; private final String[] scale; private Listener listener; - private Players players; private History history; + private Players player; private boolean parse; public static ControlDialog create() { @@ -57,8 +58,8 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis return this; } - public ControlDialog players(Players players) { - this.players = players; + public ControlDialog player(Players player) { + this.player = player; return this; } @@ -71,6 +72,7 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis for (Fragment f : activity.getSupportFragmentManager().getFragments()) if (f instanceof BottomSheetDialogFragment) return this; show(activity.getSupportFragmentManager(), null); this.listener = (Listener) activity; + this.activity = activity; return this; } @@ -83,9 +85,9 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis @Override protected void initView() { - if (players == null) dismiss(); - if (players == null) return; - binding.speed.setValue(Math.max(players.getSpeed(), 0.5f)); + if (player == null) dismiss(); + if (player == null) return; + binding.speed.setValue(Math.max(player.getSpeed(), 0.5f)); binding.player.setText(parent.control.action.player.getText()); binding.decode.setText(parent.control.action.decode.getText()); binding.ending.setText(parent.control.action.ending.getText()); @@ -98,6 +100,7 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis @Override protected void initEvent() { + binding.timer.setOnClickListener(this::onTimer); binding.speed.addOnChangeListener(this::setSpeed); for (TextView view : scales) view.setOnClickListener(this::setScale); binding.text.setOnClickListener(v -> dismiss(parent.control.action.text)); @@ -113,9 +116,14 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis binding.opening.setOnLongClickListener(v -> longClick(binding.opening, parent.control.action.opening)); } + private void onTimer(View view) { + App.post(() -> TimerDialog.create().show(activity), 200); + dismiss(); + } + private void setSpeed(@NonNull Slider slider, float value, boolean fromUser) { - parent.control.action.speed.setText(players.setSpeed(value)); - if (history != null) history.setSpeed(players.getSpeed()); + parent.control.action.speed.setText(player.setSpeed(value)); + if (history != null) history.setSpeed(player.getSpeed()); } private void setScaleText() { diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/TimerDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/TimerDialog.java new file mode 100644 index 000000000..31d0b4ff8 --- /dev/null +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/TimerDialog.java @@ -0,0 +1,95 @@ +package com.fongmi.android.tv.ui.dialog; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.viewbinding.ViewBinding; + +import com.fongmi.android.tv.databinding.DialogTimerBinding; +import com.fongmi.android.tv.player.Timer; +import com.fongmi.android.tv.utils.Util; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import java.util.Formatter; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +public class TimerDialog extends BaseDialog implements Timer.Callback { + + private DialogTimerBinding binding; + private StringBuilder builder; + private Formatter formatter; + + public static TimerDialog create() { + return new TimerDialog(); + } + + public TimerDialog() { + builder = new StringBuilder(); + formatter = new Formatter(builder, Locale.getDefault()); + } + + public void show(FragmentActivity activity) { + for (Fragment f : activity.getSupportFragmentManager().getFragments()) if (f instanceof BottomSheetDialogFragment) return; + show(activity.getSupportFragmentManager(), null); + } + + @Override + protected ViewBinding getBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + return binding = DialogTimerBinding.inflate(inflater, container, false); + } + + @Override + protected void initView() { + onTick(Timer.get().getTick()); + binding.list.setVisibility(Timer.get().isRunning() ? View.GONE : View.VISIBLE); + binding.timer.setVisibility(Timer.get().isRunning() ? View.VISIBLE : View.GONE); + } + + @Override + protected void initEvent() { + Timer.get().setCallback(this); + binding.delay.setOnClickListener(this::onDelay); + binding.reset.setOnClickListener(this::onReset); + binding.time1.setOnClickListener(this::setTimer); + binding.time2.setOnClickListener(this::setTimer); + binding.time3.setOnClickListener(this::setTimer); + binding.time4.setOnClickListener(this::setTimer); + } + + private void setTimer(View view) { + int minutes = Integer.parseInt(view.getTag().toString()); + Timer.get().set(TimeUnit.MINUTES.toMillis(minutes)); + dismiss(); + } + + private void onDelay(View view) { + Timer.get().delay(); + } + + private void onReset(View view) { + Timer.get().reset(); + dismiss(); + } + + @Override + public void onTick(long tick) { + binding.tick.setText(Util.format(builder, formatter, tick)); + } + + @Override + public void onFinish() { + dismiss(); + } + + @Override + public void dismiss() { + Timer.get().setCallback(null); + super.dismiss(); + } +} diff --git a/app/src/mobile/res/layout/dialog_control.xml b/app/src/mobile/res/layout/dialog_control.xml index c09268ec0..754d16407 100644 --- a/app/src/mobile/res/layout/dialog_control.xml +++ b/app/src/mobile/res/layout/dialog_control.xml @@ -193,6 +193,15 @@ android:textSize="14sp" tools:text="片尾" /> + + diff --git a/app/src/mobile/res/layout/dialog_timer.xml b/app/src/mobile/res/layout/dialog_timer.xml new file mode 100644 index 000000000..22c830a30 --- /dev/null +++ b/app/src/mobile/res/layout/dialog_timer.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/mobile/res/values-zh-rCN/strings.xml b/app/src/mobile/res/values-zh-rCN/strings.xml index 29e6dfcc9..c4025548d 100644 --- a/app/src/mobile/res/values-zh-rCN/strings.xml +++ b/app/src/mobile/res/values-zh-rCN/strings.xml @@ -35,6 +35,14 @@ 收藏纪录将会全部删除。 观看纪录将会全部删除。 + + 5 分钟 + 15 分钟 + 30 分钟 + 1 小时 + 延长 5 分钟 + 取消定时器 + 已复制 已于主萤幕新增捷径。 diff --git a/app/src/mobile/res/values-zh-rTW/strings.xml b/app/src/mobile/res/values-zh-rTW/strings.xml index a741f8761..ef811ef53 100644 --- a/app/src/mobile/res/values-zh-rTW/strings.xml +++ b/app/src/mobile/res/values-zh-rTW/strings.xml @@ -35,6 +35,14 @@ 收藏紀錄將會全部刪除。 觀看紀錄將會全部刪除。 + + 5 分鐘 + 15 分鐘 + 30 分鐘 + 1 小時 + 延長 5 分鐘 + 取消定時器 + 已複製 已於主螢幕新增捷徑。 diff --git a/app/src/mobile/res/values/strings.xml b/app/src/mobile/res/values/strings.xml index 6bbbd8b3d..2800af597 100644 --- a/app/src/mobile/res/values/strings.xml +++ b/app/src/mobile/res/values/strings.xml @@ -35,6 +35,14 @@ All keep records will be removed. All history records will be removed. + + 5 minutes + 15 minutes + 30 minutes + 1 hour + Add 5 minutes + Cancel timer + Copied Shortcut has been added.