Compare commits

..

No commits in common. "5227751dcad431848fe29276a0344fcd1309b227" and "1f40385786482ba9f9d84ad9584640aad579f87a" have entirely different histories.

20 changed files with 50 additions and 116 deletions

View File

@ -17,7 +17,6 @@ steps:
- echo "---------------------------------------------------------" - echo "---------------------------------------------------------"
- ./gradlew koverMergedXmlReport - ./gradlew koverMergedXmlReport
environment: environment:
TZ: Europe/Paris
SONAR_HOST_URL: SONAR_HOST_URL:
from_secret: sonarScannerHostUrl from_secret: sonarScannerHostUrl
SONAR_LOGIN: SONAR_LOGIN:
@ -51,7 +50,6 @@ steps:
- git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git - git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git
- git push pushing --tags - git push pushing --tags
environment: environment:
TZ: Europe/Paris
GITEA_USR: GITEA_USR:
from_secret: giteaUsr from_secret: giteaUsr
GITEA_PASS: GITEA_PASS:
@ -77,7 +75,10 @@ steps:
from_secret: privateKey from_secret: privateKey
command_timeout: 2m command_timeout: 2m
script: script:
- cd /home/ubuntu && sudo rm -rf /var/www/amine/version.txt && sudo chown www-data:www-data ./version.txt && sudo mv version.txt /var/www/amine/ - cd /home/ubuntu
- sudo rm -rf /var/www/amine/version.txt
- sudo chown www-data:www-data ./version.txt
- sudo mv version.txt /var/www/amine/
trigger: trigger:
event: event:
@ -116,7 +117,6 @@ steps:
- echo "Verify" - echo "Verify"
- $ANDROID_HOME/build-tools/31.0.0/apksigner verify signed.apk - $ANDROID_HOME/build-tools/31.0.0/apksigner verify signed.apk
environment: environment:
TZ: Europe/Paris
YOUR_KEYSTORE_PASSWORD: YOUR_KEYSTORE_PASSWORD:
from_secret: keyPass from_secret: keyPass
YOUR_KEY_ALIAS: YOUR_KEY_ALIAS:

View File

@ -23,7 +23,6 @@ import com.mikepenz.aboutlibraries.LibsBuilder
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 org.acra.ACRA
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
@ -130,7 +129,6 @@ class LoginActivity : AppCompatActivity(), DIAware {
private fun goToMain() { private fun goToMain() {
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
repository.updateApiVersion() repository.updateApiVersion()
ACRA.errorReporter.putCustomData("SELFOSS_API_VERSION", appSettingsService.getApiVersion().toString())
} }
val intent = Intent(this, HomeActivity::class.java) val intent = Intent(this, HomeActivity::class.java)
startActivity(intent) startActivity(intent)

View File

@ -30,8 +30,6 @@ class ReaderActivity : AppCompatActivity(), DIAware {
private lateinit var binding: ActivityReaderBinding private lateinit var binding: ActivityReaderBinding
private var allItems: ArrayList<SelfossModel.Item> = ArrayList()
override val di by closestDI() override val di by closestDI()
private val repository: Repository by instance() private val repository: Repository by instance()
private val appSettingsService: AppSettingsService by instance() private val appSettingsService: AppSettingsService by instance()
@ -63,14 +61,12 @@ class ReaderActivity : AppCompatActivity(), DIAware {
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true)
currentItem = intent.getIntExtra("currentItem", 0) if (allItems.isEmpty()) {
allItems = repository.getReaderItems()
if (allItems.isEmpty() || currentItem > allItems.size) {
finish() finish()
} }
currentItem = intent.getIntExtra("currentItem", 0)
readItem(allItems[currentItem]) readItem(allItems[currentItem])
binding.pager.adapter = ScreenSlidePagerAdapter(this) binding.pager.adapter = ScreenSlidePagerAdapter(this)
@ -218,4 +214,8 @@ class ReaderActivity : AppCompatActivity(), DIAware {
startActivity(intent) startActivity(intent)
overridePendingTransition(0, 0) overridePendingTransition(0, 0)
} }
companion object {
var allItems: ArrayList<SelfossModel.Item> = ArrayList()
}
} }

View File

@ -62,7 +62,7 @@ class ItemCardAdapter(
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate() binding.sourceTitleAndDate.text = itm.sourceAndDateText()
if (!appSettingsService.isFullHeightCardsEnabled()) { if (!appSettingsService.isFullHeightCardsEnabled()) {
binding.itemImage.maxHeight = imageMaxHeight binding.itemImage.maxHeight = imageMaxHeight
@ -132,8 +132,8 @@ class ItemCardAdapter(
private fun handleLinkOpening() { private fun handleLinkOpening() {
binding.root.setOnClickListener { binding.root.setOnClickListener {
repository.setReaderItems(items)
c.openItemUrl( c.openItemUrl(
items,
bindingAdapterPosition, bindingAdapterPosition,
items[bindingAdapterPosition].getLinkDecoded(), items[bindingAdapterPosition].getLinkDecoded(),
appSettingsService.isArticleViewerEnabled(), appSettingsService.isArticleViewerEnabled(),

View File

@ -51,7 +51,7 @@ class ItemListAdapter(
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate() binding.sourceTitleAndDate.text = itm.sourceAndDateText()
if (itm.getThumbnail(repository.baseUrl).isEmpty()) { if (itm.getThumbnail(repository.baseUrl).isEmpty()) {
@ -84,8 +84,8 @@ class ItemListAdapter(
private fun handleLinkOpening() { private fun handleLinkOpening() {
binding.root.setOnClickListener { binding.root.setOnClickListener {
repository.setReaderItems(items)
c.openItemUrl( c.openItemUrl(
items,
bindingAdapterPosition, bindingAdapterPosition,
items[bindingAdapterPosition].getLinkDecoded(), items[bindingAdapterPosition].getLinkDecoded(),
appSettingsService.isArticleViewerEnabled(), appSettingsService.isArticleViewerEnabled(),

View File

@ -78,9 +78,9 @@ class SourcesListAdapter(
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn) val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
deleteBtn.setOnClickListener { deleteBtn.setOnClickListener {
val (id, title) = items[bindingAdapterPosition] val (id) = items[bindingAdapterPosition]
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val successfullyDeletedSource = repository.deleteSource(id, title) val successfullyDeletedSource = repository.deleteSource(id)
if (successfullyDeletedSource) { if (successfullyDeletedSource) {
items.removeAt(bindingAdapterPosition) items.removeAt(bindingAdapterPosition)
notifyItemRemoved(bindingAdapterPosition) notifyItemRemoved(bindingAdapterPosition)

View File

@ -101,7 +101,7 @@ class ArticleFragment : Fragment(), DIAware {
contentText = item.content contentText = item.content
contentTitle = item.title.getHtmlDecoded() contentTitle = item.title.getHtmlDecoded()
contentImage = item.getThumbnail(repository.baseUrl) contentImage = item.getThumbnail(repository.baseUrl)
contentSource = item.sourceAuthorAndDate() contentSource = item.sourceAndDateText()
allImages = item.getImages() allImages = item.getImages()
fontSize = appSettingsService.getFontSize() fontSize = appSettingsService.getFontSize()
@ -347,7 +347,7 @@ class ArticleFragment : Fragment(), DIAware {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG)) return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG))
} catch ( e : ExecutionException) { } catch ( e : ExecutionException) {
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > jpeg > $url") e.sendSilentlyWithAcraWithName("shouldInterceptRequest > jpeg")
} }
} }
else if (url.lowercase(Locale.US).contains(".png")) { else if (url.lowercase(Locale.US).contains(".png")) {
@ -355,7 +355,7 @@ class ArticleFragment : Fragment(), DIAware {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG)) return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG))
} catch ( e : ExecutionException) { } catch ( e : ExecutionException) {
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > png > $url") e.sendSilentlyWithAcraWithName("shouldInterceptRequest > png")
} }
} }
else if (url.lowercase(Locale.US).contains(".webp")) { else if (url.lowercase(Locale.US).contains(".webp")) {
@ -363,7 +363,7 @@ class ArticleFragment : Fragment(), DIAware {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP)) return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP))
} catch ( e : ExecutionException) { } catch ( e : ExecutionException) {
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > webp > $url") e.sendSilentlyWithAcraWithName("shouldInterceptRequest > webp")
} }
} }

View File

@ -16,8 +16,7 @@ fun SelfossModel.Item.toParcelable() : ParecelableItem =
this.icon, this.icon,
this.link, this.link,
this.sourcetitle, this.sourcetitle,
this.tags.joinToString(","), this.tags.joinToString(",")
this.author
) )
fun ParecelableItem.toModel() : SelfossModel.Item = fun ParecelableItem.toModel() : SelfossModel.Item =
SelfossModel.Item( SelfossModel.Item(
@ -31,8 +30,7 @@ fun ParecelableItem.toModel() : SelfossModel.Item =
this.icon, this.icon,
this.link, this.link,
this.sourcetitle, this.sourcetitle,
this.tags.split(","), this.tags.split(",")
this.author
) )
data class ParecelableItem( data class ParecelableItem(
val id: Int, val id: Int,
@ -45,8 +43,7 @@ data class ParecelableItem(
val icon: String?, val icon: String?,
val link: String, val link: String,
val sourcetitle: String, val sourcetitle: String,
val tags: String, val tags: String
val author: String?
) : Parcelable { ) : Parcelable {
companion object { companion object {
@ -68,8 +65,7 @@ data class ParecelableItem(
icon = source.readString(), icon = source.readString(),
link = source.readString().orEmpty(), link = source.readString().orEmpty(),
sourcetitle = source.readString().orEmpty(), sourcetitle = source.readString().orEmpty(),
tags = source.readString().orEmpty(), tags = source.readString().orEmpty()
author = source.readString().orEmpty()
) )
override fun describeContents() = 0 override fun describeContents() = 0
@ -86,6 +82,5 @@ data class ParecelableItem(
dest.writeString(link) dest.writeString(link)
dest.writeString(sourcetitle) dest.writeString(sourcetitle)
dest.writeString(tags) dest.writeString(tags)
dest.writeString(author)
} }
} }

View File

@ -18,6 +18,7 @@ import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
fun Context.openItemUrl( fun Context.openItemUrl(
allItems: ArrayList<SelfossModel.Item>,
currentItem: Int, currentItem: Int,
linkDecoded: String, linkDecoded: String,
articleViewer: Boolean, articleViewer: Boolean,
@ -32,6 +33,7 @@ fun Context.openItemUrl(
).show() ).show()
} else { } else {
if (articleViewer) { if (articleViewer) {
ReaderActivity.allItems = allItems
val intent = Intent(this, ReaderActivity::class.java) val intent = Intent(this, ReaderActivity::class.java)
intent.putExtra("currentItem", currentItem) intent.putExtra("currentItem", currentItem)
app.startActivity(intent) app.startActivity(intent)

View File

@ -11,14 +11,11 @@ class DatesTest {
private val v3Date = "2013-04-07T13:43:00+01:00" private val v3Date = "2013-04-07T13:43:00+01:00"
private val v4Date = "2013-04-07 13:43:00" private val v4Date = "2013-04-07 13:43:00"
private val bug1Date = "2022-12-24T17:00:08+00"
@Test @Test
fun v3_date_should_be_parsed() { fun v3_date_should_be_parsed() {
val date = DateUtils.parseDate(v3Date) val date = DateUtils.parseDate(v3Date)
val expected = val expected = LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.of("UTC+1")) .toEpochMilliseconds()
LocalDateTime(2013, 4, 7, 14, 43, 0, 0).toInstant(TimeZone.currentSystemDefault())
.toEpochMilliseconds()
assertEquals(date, expected) assertEquals(date, expected)
} }
@ -33,14 +30,4 @@ class DatesTest {
assertEquals(date, expected) assertEquals(date, expected)
} }
@Test
fun bug1_date_should_be_parsed() {
val date = DateUtils.parseDate(bug1Date)
val expected =
LocalDateTime(2022, 12, 24, 18, 0, 8, 0).toInstant(TimeZone.currentSystemDefault())
.toEpochMilliseconds()
assertEquals(date, expected)
}
} }

View File

@ -58,7 +58,6 @@ class RepositoryTest {
data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED) data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED)
) )
every { db.itemsQueries.deleteItemsWhereSource(any()) } returns Unit
every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems()
every { db.tagsQueries.deleteAllTags() } returns Unit every { db.tagsQueries.deleteAllTags() } returns Unit
every { db.tagsQueries.transaction(any(), any()) } returns Unit every { db.tagsQueries.transaction(any(), any()) } returns Unit
@ -799,11 +798,10 @@ class RepositoryTest {
initializeRepository() initializeRepository()
var response: Boolean var response: Boolean
runBlocking { runBlocking {
response = repository.deleteSource(5, "src") response = repository.deleteSource(5)
} }
coVerify(exactly = 1) { api.deleteSource(5) } coVerify(exactly = 1) { api.deleteSource(5) }
coVerify(exactly = 1) { db.itemsQueries.deleteItemsWhereSource("src") }
assertSame(true, response) assertSame(true, response)
} }
@ -814,11 +812,10 @@ class RepositoryTest {
initializeRepository() initializeRepository()
var response: Boolean var response: Boolean
runBlocking { runBlocking {
response = repository.deleteSource(5, "src") response = repository.deleteSource(5)
} }
coVerify(exactly = 1) { api.deleteSource(5) } coVerify(exactly = 1) { api.deleteSource(5) }
coVerify(exactly = 0) { db.itemsQueries.deleteItemsWhereSource("src") }
assertSame(false, response) assertSame(false, response)
} }
@ -829,11 +826,10 @@ class RepositoryTest {
initializeRepository(MutableStateFlow(false)) initializeRepository(MutableStateFlow(false))
var response: Boolean var response: Boolean
runBlocking { runBlocking {
response = repository.deleteSource(5, "src") response = repository.deleteSource(5)
} }
coVerify(exactly = 0) { api.deleteSource(5) } coVerify(exactly = 0) { api.deleteSource(5) }
coVerify(exactly = 1) { db.itemsQueries.deleteItemsWhereSource("src") }
assertSame(false, response) assertSame(false, response)
} }

View File

@ -17,8 +17,7 @@ fun generateTestDBItems(item: FakeItemParameters = FakeItemParameters()): List<I
icon = item.icon, icon = item.icon,
link = item.link, link = item.link,
sourcetitle = item.sourcetitle, sourcetitle = item.sourcetitle,
tags = item.tags, tags = item.tags
author = item.author
) )
) )
} }
@ -36,8 +35,7 @@ fun generateTestApiItem(item: FakeItemParameters = FakeItemParameters()): List<S
icon = item.icon, icon = item.icon,
link = item.link, link = item.link,
sourcetitle = item.sourcetitle, sourcetitle = item.sourcetitle,
tags = item.tags.split(','), tags = item.tags.split(',')
author = item.author
) )
) )
} }
@ -56,5 +54,4 @@ class FakeItemParameters {
"https://ilblogdellasci.wordpress.com/2022/09/09/etica-della-ricerca-sotto-i-riflettori/" "https://ilblogdellasci.wordpress.com/2022/09/09/etica-della-ricerca-sotto-i-riflettori/"
var sourcetitle = "La Chimica e la Società" var sourcetitle = "La Chimica e la Società"
var tags = "Chimica, Testing" var tags = "Chimica, Testing"
var author = "Someone important"
} }

View File

@ -17,12 +17,10 @@ plugins {
allprojects { allprojects {
repositories { repositories {
maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")} google()
// IMPORTANT : Add back when new library added mavenCentral()
// google() jcenter()
// mavenCentral() maven { url = uri("https://www.jitpack.io") }
// jcenter()
// maven { url = uri("https://www.jitpack.io") }
} }
} }

View File

@ -2,20 +2,16 @@ val pushCache: String by settings
pluginManagement { pluginManagement {
repositories { repositories {
maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")} google()
// IMPORTANT : Add back when new plugin added gradlePluginPortal()
// google() mavenCentral()
// gradlePluginPortal()
// mavenCentral()
} }
} }
dependencyResolutionManagement { dependencyResolutionManagement {
repositories { repositories {
maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")} google()
// IMPORTANT : Add back when new library added mavenCentral()
// google()
// mavenCentral()
} }
} }

View File

@ -10,11 +10,7 @@ actual class DateUtils {
return try { return try {
Instant.parse(dateString).toEpochMilliseconds() Instant.parse(dateString).toEpochMilliseconds()
} catch (e: Exception) { } catch (e: Exception) {
var str = dateString.replace(" ", "T") LocalDateTime.parse(dateString.replace(" ", "T")).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
if (str.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}".toRegex())) {
str = str.split("+")[0]
}
LocalDateTime.parse(str).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
} }
} }

View File

@ -57,6 +57,7 @@ class SelfossModel {
val error: String, val error: String,
val icon: String? val icon: String?
) )
@Serializable @Serializable
data class Item( data class Item(
val id: Int, val id: Int,
@ -72,8 +73,7 @@ class SelfossModel {
val link: String, val link: String,
val sourcetitle: String, val sourcetitle: String,
@Serializable(with = TagsListSerializer::class) @Serializable(with = TagsListSerializer::class)
val tags: List<String>, val tags: List<String>
val author: String?
) { ) {
// TODO: maybe find a better way to handle these kind of urls // TODO: maybe find a better way to handle these kind of urls
fun getLinkDecoded(): String { fun getLinkDecoded(): String {
@ -102,14 +102,8 @@ class SelfossModel {
return stringUrl return stringUrl
} }
fun sourceAuthorAndDate(): String { fun sourceAndDateText(): String =
var txt = this.sourcetitle.getHtmlDecoded() this.sourcetitle.getHtmlDecoded() + DateUtils.parseRelativeDate(this.datetime)
if (!this.author.isNullOrBlank()) {
txt += " (by ${this.author}) "
}
txt += DateUtils.parseRelativeDate(this.datetime)
return txt
}
fun toggleStar(): Item { fun toggleStar(): Item {
this.starred = !this.starred this.starred = !this.starred
@ -117,7 +111,6 @@ class SelfossModel {
} }
} }
// TODO: this seems to be super slow. // TODO: this seems to be super slow.
object TagsListSerializer : KSerializer<List<String>> { object TagsListSerializer : KSerializer<List<String>> {
override fun deserialize(decoder: Decoder): List<String> { override fun deserialize(decoder: Decoder): List<String> {

View File

@ -47,8 +47,6 @@ class Repository(
private var fetchedSources = false private var fetchedSources = false
private var fetchedTags = false private var fetchedTags = false
private var _readerItems = ArrayList<SelfossModel.Item>()
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> { suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
// TODO: Use the updatedSince parameter // TODO: Use the updatedSince parameter
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error() var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
@ -359,20 +357,13 @@ class Repository(
return response return response
} }
suspend fun deleteSource(id: Int, title: String): Boolean { suspend fun deleteSource(id: Int): Boolean {
var success = false var success = false
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val response = api.deleteSource(id) val response = api.deleteSource(id)
success = response.isSuccess success = response.isSuccess
} }
// We filter on success or if the network isn't available
if (success || !isNetworkAvailable()) {
items = ArrayList(items.filter { it.sourcetitle != title })
setReaderItems(items)
db.itemsQueries.deleteItemsWhereSource(title)
}
return success return success
} }
@ -567,12 +558,4 @@ class Repository(
fun setSourceFilter(source: SelfossModel.Source?) { fun setSourceFilter(source: SelfossModel.Source?) {
_sourceFilter.value = source _sourceFilter.value = source
} }
fun setReaderItems(readerItems: ArrayList<SelfossModel.Item>) {
_readerItems = readerItems
}
fun getReaderItems(): ArrayList<SelfossModel.Item> {
return _readerItems
}
} }

View File

@ -51,8 +51,7 @@ fun ITEM.toView(): SelfossModel.Item =
this.icon, this.icon,
this.link, this.link,
this.sourcetitle, this.sourcetitle,
this.tags.split(","), this.tags.split(",")
this.author
) )
fun SelfossModel.Item.toEntity(): ITEM = fun SelfossModel.Item.toEntity(): ITEM =
@ -67,6 +66,5 @@ fun SelfossModel.Item.toEntity(): ITEM =
this.icon, this.icon,
this.link, this.link,
this.sourcetitle.getHtmlDecoded(), this.sourcetitle.getHtmlDecoded(),
this.tags.joinToString(","), this.tags.joinToString(",")
this.author
) )

View File

@ -1 +0,0 @@
ALTER TABLE ITEM ADD COLUMN `author` TEXT;

View File

@ -10,7 +10,6 @@ CREATE TABLE ITEM (
`link` TEXT NOT NULL, `link` TEXT NOT NULL,
`sourcetitle` TEXT NOT NULL, `sourcetitle` TEXT NOT NULL,
`tags` TEXT NOT NULL, `tags` TEXT NOT NULL,
`author` TEXT,
PRIMARY KEY(`id`) PRIMARY KEY(`id`)
); );
@ -27,8 +26,5 @@ INSERT OR REPLACE INTO ITEM VALUES ?;
deleteItem: deleteItem:
DELETE FROM ITEM WHERE `id` = ?; DELETE FROM ITEM WHERE `id` = ?;
deleteItemsWhereSource:
DELETE FROM ITEM WHERE `sourcetitle` = ?;
updateItem: updateItem:
UPDATE ITEM SET `datetime` = ?, `title` = ?, `content` = ?, `unread` = ?, `starred` = ?, `thumbnail` = ?, `icon` = ?, `link` = ?, `sourcetitle` = ?, `tags` = ? WHERE `id` = ?; UPDATE ITEM SET `datetime` = ?, `title` = ?, `content` = ?, `unread` = ?, `starred` = ?, `thumbnail` = ?, `icon` = ?, `link` = ?, `sourcetitle` = ?, `tags` = ? WHERE `id` = ?;