mirror of
https://github.com/MetaCubeX/ClashMetaForAndroid.git
synced 2024-11-16 12:02:18 +08:00
feat: show subscription
This commit is contained in:
parent
d2f5503330
commit
e06c901bf5
|
@ -20,15 +20,6 @@
|
||||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
|
||||||
<value>
|
|
||||||
<package name="" alias="false" withSubpackages="true" />
|
|
||||||
<package name="java" alias="false" withSubpackages="true" />
|
|
||||||
<package name="javax" alias="false" withSubpackages="true" />
|
|
||||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
|
||||||
<package name="" alias="true" withSubpackages="true" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
</JetCodeStyleSettings>
|
</JetCodeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
|
|
|
@ -65,4 +65,12 @@ fun Long.toBytesString(): String {
|
||||||
else ->
|
else ->
|
||||||
"$this Bytes"
|
"$this Bytes"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Double.toProgress(): Int {
|
||||||
|
return this.toInt()
|
||||||
|
}
|
||||||
|
fun Long.toDateStr(): String {
|
||||||
|
val simpleDateFormat =SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||||
|
return simpleDateFormat.format(Date(this*1000))
|
||||||
}
|
}
|
12
design/src/main/res/drawable/bg_b.xml
Normal file
12
design/src/main/res/drawable/bg_b.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="?attr/colorSurface" />
|
||||||
|
<corners
|
||||||
|
android:radius="8dp"
|
||||||
|
/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</layer-list>
|
|
@ -13,16 +13,18 @@
|
||||||
<variable
|
<variable
|
||||||
name="menu"
|
name="menu"
|
||||||
type="android.view.View.OnClickListener" />
|
type="android.view.View.OnClickListener" />
|
||||||
|
<import type="android.view.View" />
|
||||||
<import type="com.github.kr328.clash.design.util.I18nKt" />
|
<import type="com.github.kr328.clash.design.util.I18nKt" />
|
||||||
<import type="com.github.kr328.clash.design.util.IntervalKt" />
|
<import type="com.github.kr328.clash.design.util.IntervalKt" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
android:elevation="5dp"
|
||||||
android:id="@+id/root_view"
|
android:id="@+id/root_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/bg_b"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:minHeight="@dimen/item_min_height"
|
android:minHeight="@dimen/item_min_height"
|
||||||
|
@ -61,6 +63,43 @@
|
||||||
android:layout_marginTop="@dimen/item_text_margin"
|
android:layout_marginTop="@dimen/item_text_margin"
|
||||||
android:text="@{profile.pending ? @string/format_type_unsaved(I18nKt.toString(profile.type, context)) : I18nKt.toString(profile.type, context)}"
|
android:text="@{profile.pending ? @string/format_type_unsaved(I18nKt.toString(profile.type, context)) : I18nKt.toString(profile.type, context)}"
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" />
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" />
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{profile.download ==0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:text='@{profile.download >0 ?I18nKt.toBytesString(profile.download+profile.upload)+"/" :""}'
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{profile.download ==0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:text='@{profile.download >0 ?I18nKt.toBytesString(profile.total) : ""}'
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />
|
||||||
|
</LinearLayout>
|
||||||
|
<TextView
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{profile.expire==0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:text='@{profile.expire>0 ? I18nKt.toDateStr(profile.expire):""}'
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />
|
||||||
|
<ProgressBar
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:max="1000"
|
||||||
|
android:visibility="@{profile.download==0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:progress="@{profile.download>0 ?I18nKt.toProgress ((profile.download+profile.upload)/(profile.total/1000)) :0}"
|
||||||
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -74,12 +113,10 @@
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Tooltip" />
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Tooltip" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="@dimen/divider_size"
|
android:layout_width="2dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toStartOf="@id/menu_view"
|
android:layout_toStartOf="@id/menu_view"
|
||||||
android:background="?attr/colorControlHighlight"
|
android:background="@color/color_clash_dark" />
|
||||||
android:minHeight="@{@dimen/item_tailing_component_size * 1.5f}" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/menu_view"
|
android:id="@+id/menu_view"
|
||||||
|
|
|
@ -19,6 +19,11 @@ dependencies {
|
||||||
implementation(libs.androidx.room.ktx)
|
implementation(libs.androidx.room.ktx)
|
||||||
implementation(libs.kaidl.runtime)
|
implementation(libs.kaidl.runtime)
|
||||||
implementation(libs.rikkax.multiprocess)
|
implementation(libs.rikkax.multiprocess)
|
||||||
|
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
|
||||||
|
|
||||||
|
// define any required OkHttp artifacts without version
|
||||||
|
implementation("com.squareup.okhttp3:okhttp")
|
||||||
|
implementation("com.squareup.okhttp3:logging-interceptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.github.kr328.clash.service
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.kr328.clash.service.data.Database
|
import com.github.kr328.clash.service.data.Database
|
||||||
|
import com.github.kr328.clash.service.data.Imported
|
||||||
import com.github.kr328.clash.service.data.ImportedDao
|
import com.github.kr328.clash.service.data.ImportedDao
|
||||||
import com.github.kr328.clash.service.data.Pending
|
import com.github.kr328.clash.service.data.Pending
|
||||||
import com.github.kr328.clash.service.data.PendingDao
|
import com.github.kr328.clash.service.data.PendingDao
|
||||||
|
@ -13,10 +14,13 @@ import com.github.kr328.clash.service.util.directoryLastModified
|
||||||
import com.github.kr328.clash.service.util.generateProfileUUID
|
import com.github.kr328.clash.service.util.generateProfileUUID
|
||||||
import com.github.kr328.clash.service.util.importedDir
|
import com.github.kr328.clash.service.util.importedDir
|
||||||
import com.github.kr328.clash.service.util.pendingDir
|
import com.github.kr328.clash.service.util.pendingDir
|
||||||
|
import com.github.kr328.clash.service.util.sendProfileChanged
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -40,6 +44,10 @@ class ProfileManager(private val context: Context) : IProfileManager,
|
||||||
type = type,
|
type = type,
|
||||||
source = source,
|
source = source,
|
||||||
interval = 0,
|
interval = 0,
|
||||||
|
upload = 0,
|
||||||
|
total = 0,
|
||||||
|
download = 0,
|
||||||
|
expire = 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
PendingDao().insert(pending)
|
PendingDao().insert(pending)
|
||||||
|
@ -68,6 +76,10 @@ class ProfileManager(private val context: Context) : IProfileManager,
|
||||||
type = Profile.Type.File,
|
type = Profile.Type.File,
|
||||||
source = imported.source,
|
source = imported.source,
|
||||||
interval = imported.interval,
|
interval = imported.interval,
|
||||||
|
upload = imported.upload,
|
||||||
|
total = imported.total,
|
||||||
|
download = imported.download,
|
||||||
|
expire = imported.expire,
|
||||||
)
|
)
|
||||||
|
|
||||||
cloneImportedFiles(uuid, newUUID)
|
cloneImportedFiles(uuid, newUUID)
|
||||||
|
@ -93,13 +105,21 @@ class ProfileManager(private val context: Context) : IProfileManager,
|
||||||
type = imported.type,
|
type = imported.type,
|
||||||
source = source,
|
source = source,
|
||||||
interval = interval,
|
interval = interval,
|
||||||
|
upload = 0,
|
||||||
|
total = 0,
|
||||||
|
download = 0,
|
||||||
|
expire = 0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val newPending = pending.copy(
|
val newPending = pending.copy(
|
||||||
name = name,
|
name = name,
|
||||||
source = source,
|
source = source,
|
||||||
interval = interval
|
interval = interval,
|
||||||
|
upload = 0,
|
||||||
|
total = 0,
|
||||||
|
download = 0,
|
||||||
|
expire = 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
PendingDao().update(newPending)
|
PendingDao().update(newPending)
|
||||||
|
@ -108,6 +128,81 @@ class ProfileManager(private val context: Context) : IProfileManager,
|
||||||
|
|
||||||
override suspend fun update(uuid: UUID) {
|
override suspend fun update(uuid: UUID) {
|
||||||
scheduleUpdate(uuid, true)
|
scheduleUpdate(uuid, true)
|
||||||
|
ImportedDao().queryByUUID(uuid)?.let {
|
||||||
|
if (it.type == Profile.Type.Url) {
|
||||||
|
updateFlow(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateFlow(old: Imported) {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
try {
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(old.source)
|
||||||
|
.header("User-Agent", "ClashforWindows/0.19.23")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
client.newCall(request).execute().use { response ->
|
||||||
|
if (!response.isSuccessful || response.headers["subscription-userinfo"] == null) return
|
||||||
|
|
||||||
|
var upload: Long = 0
|
||||||
|
var download: Long = 0
|
||||||
|
var total: Long = 0
|
||||||
|
var expire: Long = 0
|
||||||
|
|
||||||
|
val userinfo = response.headers["subscription-userinfo"]
|
||||||
|
if (response.isSuccessful && userinfo != null) {
|
||||||
|
|
||||||
|
val flags = userinfo.split(";")
|
||||||
|
for (flag in flags) {
|
||||||
|
val info = flag.split("=")
|
||||||
|
when {
|
||||||
|
info[0].contains("upload") -> upload =
|
||||||
|
info[1].toLong()
|
||||||
|
|
||||||
|
info[0].contains("download") -> download =
|
||||||
|
info[1].toLong()
|
||||||
|
|
||||||
|
info[0].contains("total") -> total =
|
||||||
|
info[1].toLong()
|
||||||
|
|
||||||
|
info[0].contains("expire") -> {
|
||||||
|
if (info[1].isNotEmpty()) {
|
||||||
|
expire = info[1].toLong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val new = Imported(
|
||||||
|
old.uuid,
|
||||||
|
old.name,
|
||||||
|
old.type,
|
||||||
|
old.source,
|
||||||
|
old.interval,
|
||||||
|
upload,
|
||||||
|
download,
|
||||||
|
total,
|
||||||
|
expire,
|
||||||
|
old?.createdAt ?: System.currentTimeMillis()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (old != null) {
|
||||||
|
ImportedDao().update(new)
|
||||||
|
} else {
|
||||||
|
ImportedDao().insert(new)
|
||||||
|
}
|
||||||
|
|
||||||
|
PendingDao().remove(new.uuid)
|
||||||
|
context.sendProfileChanged(new.uuid)
|
||||||
|
// println(response.body!!.string())
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
System.out.println(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun commit(uuid: UUID, callback: IFetchObserver?) {
|
override suspend fun commit(uuid: UUID, callback: IFetchObserver?) {
|
||||||
|
@ -163,6 +258,10 @@ class ProfileManager(private val context: Context) : IProfileManager,
|
||||||
val type = pending?.type ?: imported?.type ?: return null
|
val type = pending?.type ?: imported?.type ?: return null
|
||||||
val source = pending?.source ?: imported?.source ?: return null
|
val source = pending?.source ?: imported?.source ?: return null
|
||||||
val interval = pending?.interval ?: imported?.interval ?: return null
|
val interval = pending?.interval ?: imported?.interval ?: return null
|
||||||
|
val upload = pending?.upload ?: imported?.upload ?: return null
|
||||||
|
val download = pending?.download ?: imported?.download ?: return null
|
||||||
|
val total = pending?.total ?: imported?.total ?: return null
|
||||||
|
val expire = pending?.expire ?: imported?.expire ?: return null
|
||||||
|
|
||||||
return Profile(
|
return Profile(
|
||||||
uuid,
|
uuid,
|
||||||
|
@ -171,6 +270,10 @@ class ProfileManager(private val context: Context) : IProfileManager,
|
||||||
source,
|
source,
|
||||||
active != null && imported?.uuid == active,
|
active != null && imported?.uuid == active,
|
||||||
interval,
|
interval,
|
||||||
|
upload,
|
||||||
|
download,
|
||||||
|
total,
|
||||||
|
expire,
|
||||||
resolveUpdatedAt(uuid),
|
resolveUpdatedAt(uuid),
|
||||||
imported != null,
|
imported != null,
|
||||||
pending != null
|
pending != null
|
||||||
|
|
|
@ -19,6 +19,8 @@ import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
@ -65,28 +67,93 @@ object ProfileProcessor {
|
||||||
.copyRecursively(context.importedDir.resolve(snapshot.uuid.toString()))
|
.copyRecursively(context.importedDir.resolve(snapshot.uuid.toString()))
|
||||||
|
|
||||||
val old = ImportedDao().queryByUUID(snapshot.uuid)
|
val old = ImportedDao().queryByUUID(snapshot.uuid)
|
||||||
|
var upload: Long = 0
|
||||||
|
var download: Long = 0
|
||||||
|
var total: Long = 0
|
||||||
|
var expire: Long = 0
|
||||||
|
if (snapshot?.type == Profile.Type.Url) {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(snapshot.source)
|
||||||
|
.header("User-Agent", "ClashforWindows/0.19.23")
|
||||||
|
.build()
|
||||||
|
|
||||||
val new = Imported(
|
client.newCall(request).execute().use { response ->
|
||||||
snapshot.uuid,
|
val userinfo = response.headers["subscription-userinfo"]
|
||||||
snapshot.name,
|
if (response.isSuccessful && userinfo != null) {
|
||||||
snapshot.type,
|
val flags = userinfo.split(";")
|
||||||
snapshot.source,
|
for (flag in flags) {
|
||||||
snapshot.interval,
|
val info = flag.split("=")
|
||||||
old?.createdAt ?: System.currentTimeMillis()
|
when {
|
||||||
)
|
info[0].contains("upload") -> upload =
|
||||||
|
info[1].toLong()
|
||||||
|
|
||||||
if (old != null) {
|
info[0].contains("download") -> download =
|
||||||
ImportedDao().update(new)
|
info[1].toLong()
|
||||||
} else {
|
|
||||||
ImportedDao().insert(new)
|
info[0].contains("total") -> total =
|
||||||
|
info[1].toLong()
|
||||||
|
|
||||||
|
info[0].contains("expire") -> {
|
||||||
|
if (info[1].isNotEmpty()) {
|
||||||
|
expire = info[1].toLong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
val new = Imported(
|
||||||
|
snapshot.uuid,
|
||||||
|
snapshot.name,
|
||||||
|
snapshot.type,
|
||||||
|
snapshot.source,
|
||||||
|
snapshot.interval,
|
||||||
|
upload,
|
||||||
|
download,
|
||||||
|
total,
|
||||||
|
expire,
|
||||||
|
old?.createdAt ?: System.currentTimeMillis()
|
||||||
|
)
|
||||||
|
if (old != null) {
|
||||||
|
ImportedDao().update(new)
|
||||||
|
} else {
|
||||||
|
ImportedDao().insert(new)
|
||||||
|
}
|
||||||
|
|
||||||
|
PendingDao().remove(snapshot.uuid)
|
||||||
|
|
||||||
|
context.pendingDir.resolve(snapshot.uuid.toString())
|
||||||
|
.deleteRecursively()
|
||||||
|
|
||||||
|
context.sendProfileChanged(snapshot.uuid)
|
||||||
|
}
|
||||||
|
} else if (snapshot?.type == Profile.Type.File) {
|
||||||
|
val new = Imported(
|
||||||
|
snapshot.uuid,
|
||||||
|
snapshot.name,
|
||||||
|
snapshot.type,
|
||||||
|
snapshot.source,
|
||||||
|
snapshot.interval,
|
||||||
|
upload,
|
||||||
|
download,
|
||||||
|
total,
|
||||||
|
expire,
|
||||||
|
old?.createdAt ?: System.currentTimeMillis()
|
||||||
|
)
|
||||||
|
if (old != null) {
|
||||||
|
ImportedDao().update(new)
|
||||||
|
} else {
|
||||||
|
ImportedDao().insert(new)
|
||||||
|
}
|
||||||
|
|
||||||
|
PendingDao().remove(snapshot.uuid)
|
||||||
|
|
||||||
|
context.pendingDir.resolve(snapshot.uuid.toString())
|
||||||
|
.deleteRecursively()
|
||||||
|
|
||||||
|
context.sendProfileChanged(snapshot.uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingDao().remove(snapshot.uuid)
|
|
||||||
|
|
||||||
context.pendingDir.resolve(snapshot.uuid.toString())
|
|
||||||
.deleteRecursively()
|
|
||||||
|
|
||||||
context.sendProfileChanged(snapshot.uuid)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,10 +248,13 @@ object ProfileProcessor {
|
||||||
when {
|
when {
|
||||||
name.isBlank() ->
|
name.isBlank() ->
|
||||||
throw IllegalArgumentException("Empty name")
|
throw IllegalArgumentException("Empty name")
|
||||||
|
|
||||||
source.isEmpty() && type != Profile.Type.File ->
|
source.isEmpty() && type != Profile.Type.File ->
|
||||||
throw IllegalArgumentException("Invalid url")
|
throw IllegalArgumentException("Invalid url")
|
||||||
|
|
||||||
source.isNotEmpty() && scheme != "https" && scheme != "http" && scheme != "content" ->
|
source.isNotEmpty() && scheme != "https" && scheme != "http" && scheme != "content" ->
|
||||||
throw IllegalArgumentException("Unsupported url $source")
|
throw IllegalArgumentException("Unsupported url $source")
|
||||||
|
|
||||||
interval != 0L && TimeUnit.MILLISECONDS.toMinutes(interval) < 15 ->
|
interval != 0L && TimeUnit.MILLISECONDS.toMinutes(interval) < 15 ->
|
||||||
throw IllegalArgumentException("Invalid interval")
|
throw IllegalArgumentException("Invalid interval")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,9 @@ data class Imported(
|
||||||
@ColumnInfo(name = "type") val type: Profile.Type,
|
@ColumnInfo(name = "type") val type: Profile.Type,
|
||||||
@ColumnInfo(name = "source") val source: String,
|
@ColumnInfo(name = "source") val source: String,
|
||||||
@ColumnInfo(name = "interval") val interval: Long,
|
@ColumnInfo(name = "interval") val interval: Long,
|
||||||
|
@ColumnInfo(name = "upload") val upload: Long,
|
||||||
|
@ColumnInfo(name = "download") val download: Long,
|
||||||
|
@ColumnInfo(name = "total") val total: Long,
|
||||||
|
@ColumnInfo(name = "expire") val expire: Long,
|
||||||
@ColumnInfo(name = "createdAt") val createdAt: Long,
|
@ColumnInfo(name = "createdAt") val createdAt: Long,
|
||||||
)
|
)
|
|
@ -14,5 +14,9 @@ data class Pending(
|
||||||
@ColumnInfo(name = "type") val type: Profile.Type,
|
@ColumnInfo(name = "type") val type: Profile.Type,
|
||||||
@ColumnInfo(name = "source") val source: String,
|
@ColumnInfo(name = "source") val source: String,
|
||||||
@ColumnInfo(name = "interval") val interval: Long,
|
@ColumnInfo(name = "interval") val interval: Long,
|
||||||
|
@ColumnInfo(name = "upload") val upload: Long,
|
||||||
|
@ColumnInfo(name = "download") val download: Long,
|
||||||
|
@ColumnInfo(name = "total") val total: Long,
|
||||||
|
@ColumnInfo(name = "expire") val expire: Long,
|
||||||
@ColumnInfo(name = "createdAt") val createdAt: Long = System.currentTimeMillis(),
|
@ColumnInfo(name = "createdAt") val createdAt: Long = System.currentTimeMillis(),
|
||||||
)
|
)
|
|
@ -92,7 +92,8 @@ private suspend fun migrationFromLegacy234(
|
||||||
type = newType,
|
type = newType,
|
||||||
source = if (newType != Profile.Type.File) cursor.getString(uri) else "",
|
source = if (newType != Profile.Type.File) cursor.getString(uri) else "",
|
||||||
interval = if (version == 2) intervalValue * 1000 else intervalValue,
|
interval = if (version == 2) intervalValue * 1000 else intervalValue,
|
||||||
)
|
0,0,0,0
|
||||||
|
)
|
||||||
|
|
||||||
val base = context.pendingDir.resolve(pending.uuid.toString())
|
val base = context.pendingDir.resolve(pending.uuid.toString())
|
||||||
|
|
||||||
|
@ -165,6 +166,7 @@ private suspend fun migrationFromLegacy1(context: Context, legacy: SQLiteDatabas
|
||||||
type = newType,
|
type = newType,
|
||||||
source = source,
|
source = source,
|
||||||
interval = 0,
|
interval = 0,
|
||||||
|
0,0,0,0
|
||||||
)
|
)
|
||||||
|
|
||||||
val base = context.pendingDir.resolve(pending.uuid.toString())
|
val base = context.pendingDir.resolve(pending.uuid.toString())
|
||||||
|
|
|
@ -133,7 +133,8 @@ class Picker(private val context: Context) {
|
||||||
imported.name,
|
imported.name,
|
||||||
imported.type,
|
imported.type,
|
||||||
imported.source,
|
imported.source,
|
||||||
imported.interval
|
imported.interval,
|
||||||
|
0,0,0,0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,11 @@ data class Profile(
|
||||||
val source: String,
|
val source: String,
|
||||||
val active: Boolean,
|
val active: Boolean,
|
||||||
val interval: Long,
|
val interval: Long,
|
||||||
|
val upload: Long,
|
||||||
|
var download: Long,
|
||||||
|
val total: Long,
|
||||||
|
val expire: Long,
|
||||||
|
|
||||||
|
|
||||||
val updatedAt: Long,
|
val updatedAt: Long,
|
||||||
val imported: Boolean,
|
val imported: Boolean,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user