Remove recordable

pull/362/head
FongMi 2 years ago
parent 7ea28f4287
commit a7ce584025
  1. 20
      app/schemas/com.fongmi.android.tv.db.AppDatabase/29.json
  2. 4
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  3. 4
      app/src/leanback/java/com/fongmi/android/tv/ui/adapter/SiteAdapter.java
  4. 28
      app/src/leanback/java/com/fongmi/android/tv/ui/dialog/SiteDialog.java
  5. 10
      app/src/leanback/res/drawable/ic_site_all.xml
  6. 10
      app/src/leanback/res/drawable/ic_site_none.xml
  7. 10
      app/src/leanback/res/drawable/ic_site_record.xml
  8. 23
      app/src/leanback/res/layout/dialog_site.xml
  9. 48
      app/src/main/java/com/fongmi/android/tv/bean/Live.java
  10. 62
      app/src/main/java/com/fongmi/android/tv/bean/Site.java
  11. 49
      app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
  12. 3
      catvod/src/main/java/com/github/catvod/utils/Prefers.java

@ -1,8 +1,8 @@
{
"formatVersion": 1,
"database": {
"version": 28,
"identityHash": "d4921f6e0b243ebdcdb3a62512537b4d",
"version": 29,
"identityHash": "fe3a6989063bdf1f7fad4037f38f3b97",
"entities": [
{
"tableName": "Keep",
@ -62,7 +62,7 @@
},
{
"tableName": "Site",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `name` TEXT, `searchable` INTEGER, `changeable` INTEGER, `recordable` INTEGER, PRIMARY KEY(`key`))",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `searchable` INTEGER, `changeable` INTEGER, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
@ -70,12 +70,6 @@
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "searchable",
"columnName": "searchable",
@ -87,12 +81,6 @@
"columnName": "changeable",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "recordable",
"columnName": "recordable",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
@ -464,7 +452,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd4921f6e0b243ebdcdb3a62512537b4d')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'fe3a6989063bdf1f7fad4037f38f3b97')"
]
}
}

@ -1016,7 +1016,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
mHistory = History.find(getHistoryKey());
mHistory = mHistory == null ? createHistory(item) : mHistory;
if (!TextUtils.isEmpty(getMark())) mHistory.setVodRemarks(getMark());
if (!getSite().isRecordable() && mHistory.getKey().equals(getHistoryKey())) mHistory.delete();
//if (!getSite().isRecordable() && mHistory.getKey().equals(getHistoryKey())) mHistory.delete();
mBinding.control.opening.setText(mHistory.getOpening() == 0 ? getString(R.string.play_op) : mPlayers.stringToTime(mHistory.getOpening()));
mBinding.control.ending.setText(mHistory.getEnding() == 0 ? getString(R.string.play_ed) : mPlayers.stringToTime(mHistory.getEnding()));
mBinding.control.speed.setText(mPlayers.setSpeed(mHistory.getSpeed()));
@ -1073,7 +1073,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
long position, duration;
mHistory.setPosition(position = mPlayers.getPosition());
mHistory.setDuration(duration = mPlayers.getDuration());
if (position >= 0 && duration > 0 && getSite().isRecordable()) App.execute(() -> mHistory.update());
//if (position >= 0 && duration > 0 && getSite().isRecordable()) App.execute(() -> mHistory.update());
if (mHistory.getEnding() > 0 && duration > 0 && mHistory.getEnding() + position >= duration) {
mClock.setCallback(null);
checkNext();

@ -71,7 +71,6 @@ public class SiteAdapter extends RecyclerView.Adapter<SiteAdapter.ViewHolder> {
private boolean getChecked(Site item) {
if (type == 1) return item.isSearchable();
if (type == 2) return item.isChangeable();
if (type == 3) return !item.isRecordable();
return false;
}
@ -79,21 +78,18 @@ public class SiteAdapter extends RecyclerView.Adapter<SiteAdapter.ViewHolder> {
if (type == 0) mListener.onItemClick(item);
if (type == 1) item.setSearchable(!item.isSearchable()).save();
if (type == 2) item.setChangeable(!item.isChangeable()).save();
if (type == 3) item.setRecordable(!item.isRecordable()).save();
if (type != 0) notifyItemChanged(position);
}
private boolean setLongListener(Site item) {
if (type == 1) setEnable(!item.isSearchable());
if (type == 2) setEnable(!item.isChangeable());
if (type == 3) setEnable(!item.isRecordable());
return true;
}
private void setEnable(boolean enable) {
if (type == 1) for (Site site : VodConfig.get().getSites()) site.setSearchable(enable).save();
if (type == 2) for (Site site : VodConfig.get().getSites()) site.setChangeable(enable).save();
if (type == 3) for (Site site : VodConfig.get().getSites()) site.setRecordable(enable).save();
notifyItemRangeChanged(0, getItemCount());
}

@ -4,7 +4,6 @@ import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.CompoundButton;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.GridLayoutManager;
@ -21,7 +20,7 @@ import com.fongmi.android.tv.ui.custom.SpaceItemDecoration;
import com.fongmi.android.tv.utils.ResUtil;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
public class SiteDialog implements SiteAdapter.OnClickListener, CompoundButton.OnCheckedChangeListener {
public class SiteDialog implements SiteAdapter.OnClickListener {
private RecyclerView.ItemDecoration decoration;
private final DialogSiteBinding binding;
@ -80,11 +79,11 @@ public class SiteDialog implements SiteAdapter.OnClickListener, CompoundButton.O
}
private void initEvent() {
binding.check.setOnCheckedChangeListener(this);
binding.all.setOnClickListener(this::setAll);
binding.none.setOnClickListener(this::setNone);
binding.mode.setOnClickListener(this::setMode);
binding.search.setOnClickListener(v -> setType(v.isActivated() ? 0 : 1));
binding.change.setOnClickListener(v -> setType(v.isActivated() ? 0 : 2));
binding.record.setOnClickListener(v -> setType(v.isActivated() ? 0 : 3));
}
private void setRecyclerView() {
@ -94,7 +93,8 @@ public class SiteDialog implements SiteAdapter.OnClickListener, CompoundButton.O
if (decoration != null) binding.recycler.removeItemDecoration(decoration);
binding.recycler.addItemDecoration(decoration = new SpaceItemDecoration(getCount(), 16));
binding.recycler.setLayoutManager(new GridLayoutManager(dialog.getContext(), getCount()));
if (!binding.mode.hasFocus()) binding.recycler.post(() -> binding.recycler.scrollToPosition(VodConfig.getHomeIndex()));
if (!binding.mode.hasFocus())
binding.recycler.post(() -> binding.recycler.scrollToPosition(VodConfig.getHomeIndex()));
}
private void setDialog() {
@ -115,22 +115,24 @@ public class SiteDialog implements SiteAdapter.OnClickListener, CompoundButton.O
private void setType(int type) {
binding.search.setActivated(type == 1);
binding.change.setActivated(type == 2);
binding.record.setActivated(type == 3);
adapter.setType(this.type = type);
}
private void setAll(View view) {
if (type == 0) return;
adapter.selectAll();
}
private void setNone(View view) {
if (type == 0) return;
adapter.cancelAll();
}
private void setMode(View view) {
Setting.putSiteMode(Math.abs(Setting.getSiteMode() - 1));
initView();
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (type == 0) buttonView.setChecked(!isChecked);
else if (isChecked) adapter.selectAll();
else adapter.cancelAll();
}
@Override
public void onItemClick(Site item) {
callback.setSite(item);

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z" />
</vector>

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z" />
</vector>

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="m17.06,13c-1.86,0 -3.42,1.33 -3.82,3.1 -0.95,-0.41 -1.82,-0.3 -2.48,-0.01 -0.41,-1.78 -1.97,-3.09 -3.82,-3.09 -2.17,0 -3.94,1.79 -3.94,4s1.77,4 3.94,4c2.06,0 3.74,-1.62 3.9,-3.68 0.34,-0.24 1.23,-0.69 2.32,0.02 0.18,2.05 1.84,3.66 3.9,3.66 2.17,0 3.94,-1.79 3.94,-4s-1.77,-4 -3.94,-4m-10.12,6.86c-1.56,0 -2.81,-1.28 -2.81,-2.86s1.26,-2.86 2.81,-2.86c1.56,0 2.81,1.28 2.81,2.86s-1.25,2.86 -2.81,2.86m10.12,0c-1.56,0 -2.81,-1.28 -2.81,-2.86s1.25,-2.86 2.81,-2.86 2.82,1.28 2.82,2.86 -1.27,2.86 -2.82,2.86m4.94,-9.36h-20v1.5h20zM15.53,2.63c-0.22,-0.49 -0.78,-0.75 -1.31,-0.58l-2.22,0.74 -2.23,-0.74 -0.05,-0.01c-0.53,-0.15 -1.09,0.13 -1.29,0.64l-2.43,6.32h12l-2.44,-6.32z" />
</vector>

@ -47,13 +47,13 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusUp="@id/search"
android:nextFocusDown="@id/record"
android:nextFocusDown="@id/all"
android:padding="8dp"
android:src="@drawable/ic_site_change"
app:tint="@color/text" />
<ImageView
android:id="@+id/record"
android:id="@+id/all"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="16dp"
@ -61,21 +61,22 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusUp="@id/change"
android:nextFocusDown="@id/check"
android:nextFocusDown="@id/none"
android:padding="8dp"
android:src="@drawable/ic_site_record"
app:tint="@color/text" />
android:src="@drawable/ic_site_all" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/check"
<ImageView
android:id="@+id/none"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="16dp"
android:background="@drawable/selector_text"
android:checked="true"
android:nextFocusUp="@id/record"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusUp="@id/all"
android:nextFocusDown="@id/mode"
app:buttonTint="@color/white" />
android:padding="8dp"
android:src="@drawable/ic_site_none" />
<ImageView
android:id="@+id/mode"
@ -85,7 +86,7 @@
android:background="@drawable/selector_text"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusUp="@id/check"
android:nextFocusUp="@id/none"
android:nextFocusDown="@id/mode"
android:padding="8dp"
tools:src="@drawable/ic_site_list" />

@ -5,6 +5,7 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import com.fongmi.android.tv.App;
@ -21,51 +22,88 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Entity(ignoredColumns = {"type", "group", "url", "jar", "logo", "epg", "ua", "click", "origin", "referer", "timeout", "header", "playerType", "channels", "groups", "core", "activated", "width"})
@Entity
public class Live {
@NonNull
@PrimaryKey
@SerializedName("name")
private String name;
@Ignore
@SerializedName("type")
private int type;
@SerializedName("boot")
private boolean boot;
@SerializedName("pass")
private boolean pass;
@Ignore
@SerializedName("group")
private String group;
@Ignore
@SerializedName("url")
private String url;
@Ignore
@SerializedName("jar")
private String jar;
@Ignore
@SerializedName("logo")
private String logo;
@Ignore
@SerializedName("epg")
private String epg;
@Ignore
@SerializedName("ua")
private String ua;
@Ignore
@SerializedName("click")
private String click;
@Ignore
@SerializedName("origin")
private String origin;
@Ignore
@SerializedName("referer")
private String referer;
@Ignore
@SerializedName("timeout")
private Integer timeout;
@Ignore
@SerializedName("header")
private JsonElement header;
@Ignore
@SerializedName("playerType")
private Integer playerType;
@Ignore
@SerializedName("channels")
private List<Channel> channels;
@Ignore
@SerializedName("groups")
private List<Group> groups;
@Ignore
@SerializedName("core")
private Core core;
@SerializedName("boot")
private boolean boot;
@SerializedName("pass")
private boolean pass;
@Ignore
private boolean activated;
@Ignore
private int width;
public static Live objectFrom(JsonElement element) {

@ -6,6 +6,7 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import com.fongmi.android.tv.App;
@ -22,47 +23,74 @@ import java.util.List;
import okhttp3.Headers;
@Entity(ignoredColumns = {"api", "ext", "jar", "click", "playUrl", "type", "indexs", "timeout", "playerType", "categories", "header", "style", "activated"})
@Entity
public class Site implements Parcelable {
@NonNull
@PrimaryKey
@SerializedName("key")
private String key;
@Ignore
@SerializedName("name")
private String name;
@Ignore
@SerializedName("api")
private String api;
@Ignore
@JsonAdapter(ExtAdapter.class)
@SerializedName("ext")
private String ext;
@Ignore
@SerializedName("jar")
private String jar;
@Ignore
@SerializedName("click")
private String click;
@Ignore
@SerializedName("playUrl")
private String playUrl;
@Ignore
@SerializedName("type")
private Integer type;
@Ignore
@SerializedName("indexs")
private Integer indexs;
@Ignore
@SerializedName("timeout")
private Integer timeout;
@Ignore
@SerializedName("playerType")
private Integer playerType;
@SerializedName("searchable")
private Integer searchable;
@SerializedName("changeable")
private Integer changeable;
@SerializedName("recordable")
private Integer recordable;
@Ignore
@SerializedName("categories")
private List<String> categories;
@Ignore
@SerializedName("header")
private JsonElement header;
@Ignore
@SerializedName("style")
private Style style;
@Ignore
private boolean activated;
public static Site objectFrom(JsonElement element) {
@ -137,18 +165,10 @@ public class Site implements Parcelable {
return type == null ? 0 : type;
}
public void setType(int type) {
this.type = type;
}
public Integer getIndexs() {
return indexs == null ? 0 : indexs;
}
public void setIndexs(Integer indexs) {
this.indexs = indexs;
}
public Integer getTimeout() {
return timeout == null ? Constant.TIMEOUT_PLAY : Math.max(timeout, 1) * 1000;
}
@ -173,14 +193,6 @@ public class Site implements Parcelable {
this.changeable = changeable;
}
public Integer getRecordable() {
return recordable == null ? 1 : recordable;
}
public void setRecordable(Integer recordable) {
this.recordable = recordable;
}
public List<String> getCategories() {
return categories == null ? Collections.emptyList() : categories;
}
@ -231,15 +243,6 @@ public class Site implements Parcelable {
return this;
}
public boolean isRecordable() {
return getRecordable() == 1;
}
public Site setRecordable(boolean recordable) {
if (getRecordable() != 0) setRecordable(recordable ? 1 : 2);
return this;
}
public boolean isEmpty() {
return getKey().isEmpty() && getName().isEmpty();
}
@ -252,7 +255,6 @@ public class Site implements Parcelable {
Site item = find(getKey());
if (item == null) return this;
if (getChangeable() != 0) setChangeable(Math.max(1, item.getChangeable()));
if (getRecordable() != 0) setRecordable(Math.max(1, item.getRecordable()));
if (getSearchable() != 0) setSearchable(Math.max(1, item.getSearchable()));
return this;
}
@ -293,7 +295,6 @@ public class Site implements Parcelable {
dest.writeValue(this.playerType);
dest.writeValue(this.searchable);
dest.writeValue(this.changeable);
dest.writeValue(this.recordable);
dest.writeStringList(this.categories);
dest.writeParcelable(this.style, flags);
dest.writeByte(this.activated ? (byte) 1 : (byte) 0);
@ -313,7 +314,6 @@ public class Site implements Parcelable {
this.playerType = (Integer) in.readValue(Integer.class.getClassLoader());
this.searchable = (Integer) in.readValue(Integer.class.getClassLoader());
this.changeable = (Integer) in.readValue(Integer.class.getClassLoader());
this.recordable = (Integer) in.readValue(Integer.class.getClassLoader());
this.categories = in.createStringArrayList();
this.style = in.readParcelable(Style.class.getClassLoader());
this.activated = in.readByte() != 0;

@ -38,7 +38,7 @@ import java.util.Locale;
@Database(entities = {Keep.class, Site.class, Live.class, Track.class, Config.class, Device.class, History.class}, version = AppDatabase.VERSION)
public abstract class AppDatabase extends RoomDatabase {
public static final int VERSION = 28;
public static final int VERSION = 29;
public static final String NAME = "tv";
public static final String SYMBOL = "@@@";
@ -80,16 +80,38 @@ public abstract class AppDatabase extends RoomDatabase {
File wal = new File(Path.tv(), NAME + "-wal");
File shm = new File(Path.tv(), NAME + "-shm");
File pref = new File(Path.tv(), NAME + "-pref");
if (db.exists()) Path.move(db, App.get().getDatabasePath(db.getName()).getAbsoluteFile());
if (wal.exists()) Path.move(wal, App.get().getDatabasePath(wal.getName()).getAbsoluteFile());
if (shm.exists()) Path.move(shm, App.get().getDatabasePath(shm.getName()).getAbsoluteFile());
if (db.exists())
Path.move(db, App.get().getDatabasePath(db.getName()).getAbsoluteFile());
if (wal.exists())
Path.move(wal, App.get().getDatabasePath(wal.getName()).getAbsoluteFile());
if (shm.exists())
Path.move(shm, App.get().getDatabasePath(shm.getName()).getAbsoluteFile());
if (pref.exists()) Prefers.restore(pref);
App.post(callback::success);
});
}
private static AppDatabase create(Context context) {
return Room.databaseBuilder(context, AppDatabase.class, NAME).addMigrations(MIGRATION_11_12).addMigrations(MIGRATION_12_13).addMigrations(MIGRATION_13_14).addMigrations(MIGRATION_14_15).addMigrations(MIGRATION_15_16).addMigrations(MIGRATION_16_17).addMigrations(MIGRATION_17_18).addMigrations(MIGRATION_18_19).addMigrations(MIGRATION_19_20).addMigrations(MIGRATION_20_21).addMigrations(MIGRATION_21_22).addMigrations(MIGRATION_22_23).addMigrations(MIGRATION_23_24).addMigrations(MIGRATION_24_25).addMigrations(MIGRATION_25_26).addMigrations(MIGRATION_26_27).allowMainThreadQueries().fallbackToDestructiveMigration().build();
return Room.databaseBuilder(context, AppDatabase.class, NAME)
.addMigrations(MIGRATION_11_12)
.addMigrations(MIGRATION_12_13)
.addMigrations(MIGRATION_13_14)
.addMigrations(MIGRATION_14_15)
.addMigrations(MIGRATION_15_16)
.addMigrations(MIGRATION_16_17)
.addMigrations(MIGRATION_17_18)
.addMigrations(MIGRATION_18_19)
.addMigrations(MIGRATION_19_20)
.addMigrations(MIGRATION_20_21)
.addMigrations(MIGRATION_21_22)
.addMigrations(MIGRATION_22_23)
.addMigrations(MIGRATION_23_24)
.addMigrations(MIGRATION_24_25)
.addMigrations(MIGRATION_25_26)
.addMigrations(MIGRATION_26_27)
.addMigrations(MIGRATION_27_28)
.addMigrations(MIGRATION_28_29)
.allowMainThreadQueries().fallbackToDestructiveMigration().build();
}
public abstract KeepDao getKeepDao();
@ -227,4 +249,21 @@ public abstract class AppDatabase extends RoomDatabase {
database.execSQL("CREATE TABLE IF NOT EXISTS `Live` (`name` TEXT NOT NULL, `boot` INTEGER NOT NULL, `pass` INTEGER NOT NULL, PRIMARY KEY(`name`))");
}
};
static final Migration MIGRATION_27_28 = new Migration(27, 28) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
Prefers.remove("danmu_size");
}
};
static final Migration MIGRATION_28_29 = new Migration(28, 29) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE Site_Backup (`key` TEXT NOT NULL, searchable INTEGER, changeable INTEGER, PRIMARY KEY (`key`))");
database.execSQL("INSERT INTO Site_Backup SELECT `key`, searchable, changeable FROM Site");
database.execSQL("DROP TABLE Site");
database.execSQL("ALTER TABLE Site_Backup RENAME to Site");
}
};
}

@ -96,8 +96,7 @@ public class Prefers {
public static void restore(File file) {
try {
Gson gson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LAZILY_PARSED_NUMBER).create();
Map<String, Object> map = gson.fromJson(Path.read(file), new TypeToken<Map<String, Object>>() {
}.getType());
Map<String, Object> map = gson.fromJson(Path.read(file), new TypeToken<Map<String, Object>>() {}.getType());
for (Map.Entry<String, ?> entry : map.entrySet()) Prefers.put(entry.getKey(), convert(entry));
} catch (Exception e) {
e.printStackTrace();

Loading…
Cancel
Save