diff --git a/app/src/main/java/com/fongmi/android/tv/Setting.java b/app/src/main/java/com/fongmi/android/tv/Setting.java index 6e51f445e..17105a442 100644 --- a/app/src/main/java/com/fongmi/android/tv/Setting.java +++ b/app/src/main/java/com/fongmi/android/tv/Setting.java @@ -210,6 +210,14 @@ public class Setting { Prefers.put("site_mode", mode); } + public static int getSyncMode() { + return Prefers.getInt("sync_mode"); + } + + public static void putSyncMode(int mode) { + Prefers.put("sync_mode", mode); + } + public static boolean isBootLive() { return Prefers.getBoolean("boot_live"); } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Keep.java b/app/src/main/java/com/fongmi/android/tv/bean/Keep.java index 397a174d6..97f2d31ce 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Keep.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Keep.java @@ -156,7 +156,7 @@ public class Keep { for (Keep target : targets) { for (Config config : configs) { if (target.getCid() == config.getId()) { - target.save(Config.find(config, 0).getId()); + target.save(Config.find(config).getId()); } } } diff --git a/app/src/main/java/com/fongmi/android/tv/server/process/Action.java b/app/src/main/java/com/fongmi/android/tv/server/process/Action.java index 21d9f4c8a..61ab1f2a2 100644 --- a/app/src/main/java/com/fongmi/android/tv/server/process/Action.java +++ b/app/src/main/java/com/fongmi/android/tv/server/process/Action.java @@ -123,25 +123,25 @@ public class Action implements Process { } private void onCast(Map params) { - Config config = Config.find(params.get("url"), 0); + Config config = Config.objectFrom(params.get("config")); Device device = Device.objectFrom(params.get("device")); History history = History.objectFrom(params.get("history")); - CastEvent.post(config, device, history); + CastEvent.post(Config.find(config), device, history); } private void onSync(Map params) { - boolean sync = Objects.equals(params.get("mode"), "0"); boolean keep = Objects.equals(params.get("type"), "keep"); + boolean force = Objects.equals(params.get("force"), "true"); boolean history = Objects.equals(params.get("type"), "history"); - Device device = Device.objectFrom(params.get("device")); - if (params.get("device") != null && sync) { + String mode = Objects.requireNonNullElse(params.get("mode"), "0"); + if (params.get("device") != null && (mode.equals("0") || mode.equals("2"))) { + Device device = Device.objectFrom(params.get("device")); if (history) sendHistory(device, params); else if (keep) sendKeep(device); } - if (history) { - syncHistory(params); - } else if (keep) { - syncKeep(params); + if (mode.equals("0") || mode.equals("1")) { + if (history) syncHistory(params, force); + else if (keep) syncKeep(params, force); } } @@ -170,10 +170,10 @@ public class Action implements Process { private void sendHistory(Device device, Map params) { try { - String url = Objects.requireNonNullElse(params.get("url"), VodConfig.getUrl()); + Config config = Config.find(Config.objectFrom(params.get("config"))); FormBody.Builder body = new FormBody.Builder(); - body.add("url", url); - body.add("targets", App.gson().toJson(History.get(Config.find(url, 0).getId()))); + body.add("config", config.toString()); + body.add("targets", App.gson().toJson(History.get(config.getId()))); OkHttp.newCall(OkHttp.client(Constant.TIMEOUT_SYNC), device.getIp().concat("/action?do=sync&mode=0&type=history"), body.build()).execute(); } catch (Exception e) { App.post(() -> Notify.show(e.getMessage())); @@ -191,14 +191,11 @@ public class Action implements Process { } } - public void syncHistory(Map params) { - String url = params.get("url"); - if (TextUtils.isEmpty(url)) return; - Config config = Config.find(url, 0); - boolean replace = Objects.equals(params.get("mode"), "1"); + public void syncHistory(Map params, boolean force) { + Config config = Config.find(Config.objectFrom(params.get("config"))); List targets = History.arrayFrom(params.get("targets")); if (VodConfig.get().getConfig().equals(config)) { - if (replace) History.delete(config.getId()); + if (force) History.delete(config.getId()); History.sync(targets); } else { VodConfig.load(config, getCallback(targets)); @@ -221,14 +218,13 @@ public class Action implements Process { }; } - private void syncKeep(Map params) { - List configs = Config.arrayFrom(params.get("configs")); + private void syncKeep(Map params, boolean force) { List targets = Keep.arrayFrom(params.get("targets")); - boolean replace = Objects.equals(params.get("mode"), "1"); + List configs = Config.arrayFrom(params.get("configs")); if (TextUtils.isEmpty(VodConfig.getUrl()) && configs.size() > 0) { - VodConfig.load(Config.find(configs.get(0), 0), getCallback(configs, targets)); + VodConfig.load(Config.find(configs.get(0)), getCallback(configs, targets)); } else { - if (replace) Keep.deleteAll(); + if (force) Keep.deleteAll(); Keep.sync(configs, targets); } } diff --git a/app/src/main/java/com/fongmi/android/tv/utils/ResUtil.java b/app/src/main/java/com/fongmi/android/tv/utils/ResUtil.java index 66f4821e6..5aabf8608 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/ResUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/ResUtil.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Paint; import android.graphics.Point; import android.graphics.drawable.Drawable; @@ -119,6 +120,10 @@ public class ResUtil { return App.get().getResources().getStringArray(resId); } + public static TypedArray getTypedArray(@ArrayRes int resId) { + return App.get().getResources().obtainTypedArray(resId); + } + public static Drawable getDrawable(@DrawableRes int resId) { return ContextCompat.getDrawable(App.get(), resId); } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java index cd7d07403..52ca9727f 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java @@ -1,6 +1,5 @@ package com.fongmi.android.tv.ui.dialog; -import android.net.Uri; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,18 +18,18 @@ import com.android.cast.dlna.dmc.control.ServiceActionCallback; import com.fongmi.android.tv.App; import com.fongmi.android.tv.Constant; import com.fongmi.android.tv.R; -import com.fongmi.android.tv.api.config.VodConfig; +import com.fongmi.android.tv.bean.CastVideo; +import com.fongmi.android.tv.bean.Config; import com.fongmi.android.tv.bean.Device; import com.fongmi.android.tv.bean.History; -import com.fongmi.android.tv.utils.DLNADevice; -import com.fongmi.android.tv.bean.CastVideo; -import com.fongmi.android.tv.event.ScanEvent; -import com.fongmi.android.tv.utils.ScanTask; import com.fongmi.android.tv.databinding.DialogDeviceBinding; +import com.fongmi.android.tv.event.ScanEvent; import com.fongmi.android.tv.server.Server; import com.fongmi.android.tv.ui.activity.ScanActivity; import com.fongmi.android.tv.ui.adapter.DeviceAdapter; +import com.fongmi.android.tv.utils.DLNADevice; import com.fongmi.android.tv.utils.Notify; +import com.fongmi.android.tv.utils.ScanTask; import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Path; import com.github.catvod.utils.Util; @@ -68,18 +67,17 @@ public class CastDialog extends BaseDialog implements DeviceAdapter.OnClickListe } public CastDialog() { - client = OkHttp.client(Constant.TIMEOUT_SYNC); body = new FormBody.Builder(); body.add("device", Device.get().toString()); - if (VodConfig.getUrl() != null) body.add("url", VodConfig.getUrl()); + body.add("config", Config.vod().toString()); + client = OkHttp.client(Constant.TIMEOUT_SYNC); } public CastDialog history(History history) { String id = history.getVodId(); String fd = history.getVodId(); if (fd.startsWith("/")) fd = Server.get().getAddress() + "/file" + fd.replace(Path.rootPath(), ""); - if (fd.startsWith("file")) fd = Server.get().getAddress() + "/" + fd.replace(Path.rootPath(), "").replace("://", ""); - if (fd.startsWith("http://127.0.0.1:7777")) fd = Uri.parse(fd).getQueryParameter("url"); + if (fd.startsWith("file")) fd = Server.get().getAddress() + "/" + fd.replace(Path.rootPath(), ""); if (fd.contains("127.0.0.1")) fd = fd.replace("127.0.0.1", Util.getIp()); body.add("history", history.toString().replace(id, fd)); return this; @@ -136,16 +134,16 @@ public class CastDialog extends BaseDialog implements DeviceAdapter.OnClickListe DLNACastManager.INSTANCE.registerDeviceListener(this); } + private void onScan() { + ScanActivity.start(getActivity()); + } + private void onRefresh() { if (fm) ScanTask.create(this).start(adapter.getIps()); DLNACastManager.INSTANCE.search(null); adapter.clear(); } - private void onScan() { - ScanActivity.start(getActivity()); - } - private void onCasted() { listener.onCasted(); dismiss(); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SyncDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SyncDialog.java index 123c8a1ca..87464275b 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SyncDialog.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SyncDialog.java @@ -1,6 +1,8 @@ package com.fongmi.android.tv.ui.dialog; +import android.content.res.TypedArray; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; @@ -12,18 +14,20 @@ import androidx.viewbinding.ViewBinding; import com.fongmi.android.tv.App; import com.fongmi.android.tv.Constant; import com.fongmi.android.tv.R; +import com.fongmi.android.tv.Setting; import com.fongmi.android.tv.api.config.VodConfig; import com.fongmi.android.tv.bean.Config; import com.fongmi.android.tv.bean.Device; import com.fongmi.android.tv.bean.History; import com.fongmi.android.tv.bean.Keep; -import com.fongmi.android.tv.event.ScanEvent; -import com.fongmi.android.tv.utils.ScanTask; import com.fongmi.android.tv.databinding.DialogDeviceBinding; +import com.fongmi.android.tv.event.ScanEvent; import com.fongmi.android.tv.impl.Callback; import com.fongmi.android.tv.ui.activity.ScanActivity; import com.fongmi.android.tv.ui.adapter.DeviceAdapter; import com.fongmi.android.tv.utils.Notify; +import com.fongmi.android.tv.utils.ResUtil; +import com.fongmi.android.tv.utils.ScanTask; import com.github.catvod.net.OkHttp; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; @@ -33,6 +37,7 @@ import org.greenrobot.eventbus.ThreadMode; import java.io.IOException; import java.util.List; +import java.util.Locale; import okhttp3.Call; import okhttp3.FormBody; @@ -43,6 +48,7 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe private final FormBody.Builder body; private final OkHttpClient client; + private final TypedArray mode; private DialogDeviceBinding binding; private DeviceAdapter adapter; private String type; @@ -53,23 +59,22 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe public SyncDialog() { client = OkHttp.client(Constant.TIMEOUT_SYNC); + mode = ResUtil.getTypedArray(R.array.cast_mode); body = new FormBody.Builder(); } public SyncDialog history() { - type = "history"; body.add("device", Device.get().toString()); + body.add("config", Config.vod().toString()); body.add("targets", App.gson().toJson(History.get())); - if (VodConfig.getUrl() != null) body.add("url", VodConfig.getUrl()); - return this; + return type("history"); } public SyncDialog keep() { - type = "keep"; body.add("device", Device.get().toString()); body.add("targets", App.gson().toJson(Keep.getVod())); body.add("configs", App.gson().toJson(Config.findUrls())); - return this; + return type("keep"); } public void show(FragmentActivity activity) { @@ -77,6 +82,11 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe show(activity.getSupportFragmentManager(), null); } + private SyncDialog type(String type) { + this.type = type; + return this; + } + @Override protected ViewBinding getBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { return binding = DialogDeviceBinding.inflate(inflater, container, false); @@ -84,13 +94,16 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe @Override protected void initView() { + binding.mode.setVisibility(View.VISIBLE); EventBus.getDefault().register(this); setRecyclerView(); getDevice(); + setMode(); } @Override protected void initEvent() { + binding.mode.setOnClickListener(v -> onMode()); binding.scan.setOnClickListener(v -> onScan()); binding.refresh.setOnClickListener(v -> onRefresh()); } @@ -105,21 +118,30 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe if (adapter.getItemCount() == 0) App.post(this::onRefresh, 1000); } - private void onRefresh() { - ScanTask.create(this).start(adapter.getIps()); - adapter.clear(); + private void setMode() { + int index = Setting.getSyncMode(); + binding.mode.setImageResource(mode.getResourceId(index, 0)); + binding.mode.setTag(String.valueOf(index)); + } + + private void onMode() { + int index = Setting.getSyncMode(); + Setting.putSyncMode(index = index == mode.length() - 1 ? 0 : ++index); + binding.mode.setImageResource(mode.getResourceId(index, 0)); + binding.mode.setTag(String.valueOf(index)); } private void onScan() { ScanActivity.start(getActivity()); } - private void onSuccess() { - dismiss(); + private void onRefresh() { + ScanTask.create(this).start(adapter.getIps()); + adapter.clear(); } - private void onError() { - Notify.show(R.string.device_offline); + private void onSuccess() { + dismiss(); } @Subscribe(threadMode = ThreadMode.MAIN) @@ -134,12 +156,16 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe @Override public void onItemClick(Device item) { - OkHttp.newCall(client, item.getIp().concat("/action?do=sync&mode=0&type=").concat(type), body.build()).enqueue(getCallback()); + OkHttp.newCall(client, String.format(Locale.getDefault(), "%s/action?do=sync&mode=%s&type=%s", item.getIp(), binding.mode.getTag().toString(), type), body.build()).enqueue(getCallback()); } @Override public boolean onLongClick(Device item) { - OkHttp.newCall(client, item.getIp().concat("/action?do=sync&mode=1&type=").concat(type), body.build()).enqueue(getCallback()); + String mode = binding.mode.getTag().toString(); + if (mode.equals("0")) return false; + if (mode.equals("2") && type.equals("keep")) Keep.deleteAll(); + if (mode.equals("2") && type.equals("history")) History.delete(VodConfig.getCid()); + OkHttp.newCall(client, String.format(Locale.getDefault(), "%s/action?do=sync&mode=%s&type=%s&force=true", item.getIp(), binding.mode.getTag().toString(), type), body.build()).enqueue(getCallback()); return true; } @@ -152,7 +178,7 @@ public class SyncDialog extends BaseDialog implements DeviceAdapter.OnClickListe @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { - App.post(() -> onError()); + App.post(() -> Notify.show(e.getMessage())); } }; } diff --git a/app/src/mobile/res/drawable/ic_sync_download.xml b/app/src/mobile/res/drawable/ic_sync_download.xml new file mode 100644 index 000000000..5252b67f1 --- /dev/null +++ b/app/src/mobile/res/drawable/ic_sync_download.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/mobile/res/drawable/ic_sync_two.xml b/app/src/mobile/res/drawable/ic_sync_two.xml new file mode 100644 index 000000000..205b8023a --- /dev/null +++ b/app/src/mobile/res/drawable/ic_sync_two.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/mobile/res/drawable/ic_sync_upload.xml b/app/src/mobile/res/drawable/ic_sync_upload.xml new file mode 100644 index 000000000..ee521048e --- /dev/null +++ b/app/src/mobile/res/drawable/ic_sync_upload.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/mobile/res/layout/dialog_device.xml b/app/src/mobile/res/layout/dialog_device.xml index 723a3e778..6b770c518 100644 --- a/app/src/mobile/res/layout/dialog_device.xml +++ b/app/src/mobile/res/layout/dialog_device.xml @@ -23,6 +23,17 @@ android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" /> + + + + + + @drawable/ic_sync_two + @drawable/ic_sync_upload + @drawable/ic_sync_download + + + \ No newline at end of file