refactor packages
This commit is contained in:
@ -67,45 +67,52 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
compose true
|
||||
buildConfig true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = '1.3.1'
|
||||
kotlinCompilerExtensionVersion = "1.5.8"
|
||||
}
|
||||
packagingOptions {
|
||||
resources {
|
||||
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
||||
}
|
||||
}
|
||||
namespace 'app.omnivore.omnivore'
|
||||
namespace "app.omnivore.omnivore"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def nav_version = "2.5.3"
|
||||
def nav_version = ""
|
||||
|
||||
implementation("androidx.core:core-ktx:1.12.0")
|
||||
implementation "androidx.compose.ui:ui:$compose_version"
|
||||
implementation "androidx.compose.material:material:$compose_version"
|
||||
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
||||
implementation "androidx.compose.material:material-icons-extended:$compose_version"
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
|
||||
implementation 'androidx.activity:activity-compose:1.8.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||
implementation 'com.google.android.gms:play-services-base:18.1.0'
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.gms:play-services-base:18.3.0")
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
|
||||
|
||||
implementation "androidx.navigation:navigation-compose:$nav_version"
|
||||
// Compose
|
||||
def composeBom = platform('androidx.compose:compose-bom:2024.01.00')
|
||||
implementation(composeBom)
|
||||
androidTestImplementation(composeBom)
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
|
||||
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
|
||||
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
|
||||
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
|
||||
implementation("androidx.compose.material3:material3")
|
||||
implementation("androidx.compose.ui:ui:")
|
||||
implementation("androidx.compose.material:material")
|
||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||
implementation("androidx.compose.material:material-icons-extended")
|
||||
implementation("androidx.activity:activity-compose:1.8.2")
|
||||
implementation("androidx.navigation:navigation-compose:2.7.6")
|
||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||
|
||||
// Testing
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
|
||||
// Jetpack Lifecycle deps
|
||||
|
||||
// ViewModel
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
|
||||
@ -114,7 +121,7 @@ dependencies {
|
||||
|
||||
// LiveData
|
||||
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
|
||||
implementation("androidx.compose.runtime:runtime-livedata:1.3.2")
|
||||
implementation("androidx.compose.runtime:runtime-livedata:1.6.0")
|
||||
|
||||
// Saved state module for ViewModel
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
|
||||
@ -126,8 +133,8 @@ dependencies {
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
|
||||
// coroutines
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
|
||||
|
||||
implementation "androidx.security:security-crypto:1.0.0"
|
||||
implementation "androidx.datastore:datastore-preferences:1.0.0"
|
||||
@ -138,29 +145,28 @@ dependencies {
|
||||
|
||||
implementation("com.apollographql.apollo3:apollo-runtime:3.8.2")
|
||||
|
||||
implementation("androidx.compose.material3:material3:1.1.2")
|
||||
implementation 'androidx.compose.material3:material3-window-size-class:1.1.2'
|
||||
|
||||
implementation 'com.google.android.gms:play-services-auth:20.4.0'
|
||||
implementation "com.google.accompanist:accompanist-systemuicontroller:0.25.1"
|
||||
implementation "com.google.accompanist:accompanist-flowlayout:0.25.1"
|
||||
|
||||
implementation 'io.coil-kt:coil-compose:2.3.0'
|
||||
implementation("com.google.android.gms:play-services-auth:20.7.0")
|
||||
implementation("com.google.accompanist:accompanist-systemuicontroller:0.34.0")
|
||||
implementation("com.google.accompanist:accompanist-flowlayout:0.32.0")
|
||||
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
implementation 'com.pspdfkit:pspdfkit:8.9.1'
|
||||
implementation("io.coil-kt:coil-compose:2.5.0")
|
||||
|
||||
implementation 'com.posthog.android:posthog:2.0.3'
|
||||
implementation 'io.intercom.android:intercom-sdk:15.1.0'
|
||||
implementation("com.google.code.gson:gson:2.10")
|
||||
implementation("com.pspdfkit:pspdfkit:8.9.1")
|
||||
|
||||
implementation("com.posthog.android:posthog:2.0.3")
|
||||
implementation("io.intercom.android:intercom-sdk:15.1.0")
|
||||
|
||||
// Room Deps
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
implementation "androidx.room:room-ktx:$room_version"
|
||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
implementation("androidx.room:room-runtime:$room_version")
|
||||
implementation("androidx.room:room-ktx:$room_version")
|
||||
annotationProcessor("androidx.room:room-compiler:$room_version")
|
||||
kapt("androidx.room:room-compiler:$room_version")
|
||||
|
||||
implementation 'com.github.jeziellago:compose-markdown:0.3.3'
|
||||
implementation "io.github.dokar3:chiptextfield:0.4.7"
|
||||
implementation("com.github.jeziellago:compose-markdown:0.3.3")
|
||||
implementation("io.github.dokar3:chiptextfield-m3:0.6.5")
|
||||
}
|
||||
|
||||
apollo {
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.save.SaveSheetActivity"
|
||||
android:name=".feature.save.SaveSheetActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AppCompat.Translucent">
|
||||
<intent-filter>
|
||||
@ -47,12 +47,12 @@
|
||||
android:windowSoftInputMode="adjustNothing" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.reader.PDFReaderActivity"
|
||||
android:name=".feature.reader.PDFReaderActivity"
|
||||
android:theme="@style/Theme.AppCompat.NoActionBar"
|
||||
android:windowSoftInputMode="adjustNothing" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.reader.WebReaderLoadingContainerActivity"
|
||||
android:name=".feature.reader.WebReaderLoadingContainerActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.Omnivore"/>
|
||||
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
package app.omnivore.omnivore
|
||||
|
||||
import android.content.Context
|
||||
import com.posthog.android.PostHog
|
||||
import com.posthog.android.Properties
|
||||
import io.intercom.android.sdk.Intercom
|
||||
import io.intercom.android.sdk.identity.Registration
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class EventTracker @Inject constructor(val app: Context) {
|
||||
private val posthog: PostHog
|
||||
|
||||
init {
|
||||
val posthogClientKey = app.getString(R.string.posthog_client_key)
|
||||
val posthogInstanceAddress = app.getString(R.string.posthog_instance_address)
|
||||
|
||||
posthog = PostHog.Builder(app, posthogClientKey, posthogInstanceAddress)
|
||||
.captureApplicationLifecycleEvents()
|
||||
.collectDeviceId(false)
|
||||
.build()
|
||||
|
||||
PostHog.setSingletonInstance(posthog)
|
||||
}
|
||||
|
||||
fun registerUser(userID: String, intercomHash: String?, isDebug: Boolean) {
|
||||
posthog.identify(userID)
|
||||
if (!isDebug) {
|
||||
Intercom.client().loginIdentifiedUser(Registration.create().withUserId(userID))
|
||||
intercomHash?.let { intercomHash ->
|
||||
Intercom.client().setUserHash(intercomHash)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun track(eventName: String, properties: Properties = Properties()) {
|
||||
posthog.capture(eventName, properties)
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
posthog.reset()
|
||||
}
|
||||
}
|
||||
@ -12,15 +12,15 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import app.omnivore.omnivore.ui.auth.LoginViewModel
|
||||
import app.omnivore.omnivore.ui.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.ui.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.ui.library.LibraryViewModel
|
||||
import app.omnivore.omnivore.ui.library.SearchViewModel
|
||||
import app.omnivore.omnivore.ui.root.RootView
|
||||
import app.omnivore.omnivore.ui.save.SaveViewModel
|
||||
import app.omnivore.omnivore.ui.settings.SettingsViewModel
|
||||
import app.omnivore.omnivore.ui.theme.OmnivoreTheme
|
||||
import app.omnivore.omnivore.feature.auth.LoginViewModel
|
||||
import app.omnivore.omnivore.feature.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.feature.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.feature.library.LibraryViewModel
|
||||
import app.omnivore.omnivore.feature.library.SearchViewModel
|
||||
import app.omnivore.omnivore.feature.root.RootView
|
||||
import app.omnivore.omnivore.feature.save.SaveViewModel
|
||||
import app.omnivore.omnivore.feature.settings.SettingsViewModel
|
||||
import app.omnivore.omnivore.feature.theme.OmnivoreTheme
|
||||
import com.pspdfkit.PSPDFKit
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
package app.omnivore.omnivore
|
||||
|
||||
sealed class Routes(val route: String) {
|
||||
object Library : Routes("Library")
|
||||
object Settings: Routes("Settings")
|
||||
object Search: Routes("Search")
|
||||
object Documentation: Routes("Documentation")
|
||||
object PrivacyPolicy: Routes("PrivacyPolicy")
|
||||
object TermsAndConditions: Routes("TermsAndConditions")
|
||||
object Notebook: Routes("Notebook")
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package app.omnivore.omnivore.core.analytics
|
||||
|
||||
import android.content.Context
|
||||
import app.omnivore.omnivore.R
|
||||
import com.posthog.android.PostHog
|
||||
import com.posthog.android.Properties
|
||||
import io.intercom.android.sdk.Intercom
|
||||
import io.intercom.android.sdk.identity.Registration
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class EventTracker @Inject constructor(val app: Context) {
|
||||
private val posthog: PostHog
|
||||
|
||||
init {
|
||||
val posthogClientKey = app.getString(R.string.posthog_client_key)
|
||||
val posthogInstanceAddress = app.getString(R.string.posthog_instance_address)
|
||||
|
||||
posthog = PostHog.Builder(app, posthogClientKey, posthogInstanceAddress)
|
||||
.captureApplicationLifecycleEvents()
|
||||
.collectDeviceId(false)
|
||||
.build()
|
||||
|
||||
PostHog.setSingletonInstance(posthog)
|
||||
}
|
||||
|
||||
fun registerUser(userID: String, intercomHash: String?, isDebug: Boolean) {
|
||||
posthog.identify(userID)
|
||||
if (!isDebug) {
|
||||
Intercom.client().loginIdentifiedUser(Registration.create().withUserId(userID))
|
||||
intercomHash?.let { intercomHash ->
|
||||
Intercom.client().setUserHash(intercomHash)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun track(eventName: String, properties: Properties = Properties()) {
|
||||
posthog.capture(eventName, properties)
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
posthog.reset()
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,11 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import app.omnivore.omnivore.network.*
|
||||
import app.omnivore.omnivore.persistence.AppDatabase
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.database.AppDatabase
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import javax.inject.Inject
|
||||
@ -1,11 +1,14 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.network.*
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemAndHighlightCrossRef
|
||||
import app.omnivore.omnivore.persistence.entities.saveHighlightChange
|
||||
import app.omnivore.omnivore.core.network.CreateHighlightParams
|
||||
import app.omnivore.omnivore.core.network.DeleteHighlightParams
|
||||
import app.omnivore.omnivore.core.network.MergeHighlightsParams
|
||||
import app.omnivore.omnivore.core.network.UpdateHighlightParams
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemAndHighlightCrossRef
|
||||
import app.omnivore.omnivore.core.database.entities.saveHighlightChange
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -49,7 +52,7 @@ suspend fun DataService.createWebHighlight(jsonString: String, colorName: String
|
||||
}
|
||||
|
||||
suspend fun DataService.createNoteHighlight(savedItemId: String, note: String): String {
|
||||
val shortId = NanoId.generate(size=14)
|
||||
val shortId = NanoId.generate(size = 14)
|
||||
val createHighlightId = UUID.randomUUID().toString()
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
@ -1,9 +1,14 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.network.*
|
||||
import app.omnivore.omnivore.persistence.entities.*
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.network.savedItem
|
||||
import app.omnivore.omnivore.core.network.savedItemUpdates
|
||||
import app.omnivore.omnivore.core.network.search
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
|
||||
suspend fun DataService.librarySearch(cursor: String?, query: String): SearchResult {
|
||||
val searchResult = networker.search(cursor = cursor, limit = 10, query = query)
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
|
||||
import java.security.SecureRandom
|
||||
@ -1,8 +1,8 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.network.ReadingProgressParams
|
||||
import app.omnivore.omnivore.network.updateReadingProgress
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.network.ReadingProgressParams
|
||||
import app.omnivore.omnivore.core.network.updateReadingProgress
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -1,6 +1,6 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import app.omnivore.omnivore.network.savedItemLabels
|
||||
import app.omnivore.omnivore.core.network.savedItemLabels
|
||||
|
||||
suspend fun DataService.syncLabels() {
|
||||
val fetchedLabels = networker.savedItemLabels()
|
||||
@ -1,9 +1,9 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.network.archiveSavedItem
|
||||
import app.omnivore.omnivore.network.deleteSavedItem
|
||||
import app.omnivore.omnivore.network.unarchiveSavedItem
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.network.archiveSavedItem
|
||||
import app.omnivore.omnivore.core.network.deleteSavedItem
|
||||
import app.omnivore.omnivore.core.network.unarchiveSavedItem
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@ -54,3 +54,4 @@ suspend fun DataService.unarchiveSavedItem(itemID: String) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,22 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.core.network.ReadingProgressParams
|
||||
import app.omnivore.omnivore.core.network.createHighlight
|
||||
import app.omnivore.omnivore.core.network.deleteHighlights
|
||||
import app.omnivore.omnivore.core.network.deleteSavedItem
|
||||
import app.omnivore.omnivore.core.network.mergeHighlights
|
||||
import app.omnivore.omnivore.core.network.updateArchiveStatusSavedItem
|
||||
import app.omnivore.omnivore.core.network.updateHighlight
|
||||
import app.omnivore.omnivore.core.network.updateReadingProgress
|
||||
import app.omnivore.omnivore.graphql.generated.type.CreateHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.HighlightType
|
||||
import app.omnivore.omnivore.graphql.generated.type.MergeHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdateHighlightInput
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.network.*
|
||||
import app.omnivore.omnivore.persistence.entities.HighlightChange
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import app.omnivore.omnivore.persistence.entities.highlightChangeToHighlight
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.database.entities.HighlightChange
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.highlightChangeToHighlight
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package app.omnivore.omnivore.core.database
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.HighlightChange
|
||||
import app.omnivore.omnivore.core.database.entities.HighlightChangesDao
|
||||
import app.omnivore.omnivore.core.database.entities.HighlightDao
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemAndHighlightCrossRef
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemAndHighlightCrossRefDao
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemAndSavedItemLabelCrossRef
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemAndSavedItemLabelCrossRefDao
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemDao
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabelDao
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlightsDao
|
||||
import app.omnivore.omnivore.core.database.entities.Viewer
|
||||
import app.omnivore.omnivore.core.database.entities.ViewerDao
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
Viewer::class,
|
||||
SavedItem::class,
|
||||
SavedItemLabel::class,
|
||||
Highlight::class,
|
||||
HighlightChange::class,
|
||||
SavedItemAndSavedItemLabelCrossRef::class,
|
||||
SavedItemAndHighlightCrossRef::class
|
||||
],
|
||||
version = 24
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun viewerDao(): ViewerDao
|
||||
abstract fun savedItemDao(): SavedItemDao
|
||||
abstract fun highlightDao(): HighlightDao
|
||||
abstract fun highlightChangesDao(): HighlightChangesDao
|
||||
abstract fun savedItemLabelDao(): SavedItemLabelDao
|
||||
abstract fun savedItemWithLabelsAndHighlightsDao(): SavedItemWithLabelsAndHighlightsDao
|
||||
abstract fun savedItemAndSavedItemLabelCrossRefDao(): SavedItemAndSavedItemLabelCrossRefDao
|
||||
abstract fun savedItemAndHighlightCrossRefDao(): SavedItemAndHighlightCrossRefDao
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence
|
||||
package app.omnivore.omnivore.core.database
|
||||
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
@ -1,7 +1,7 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.*
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import android.util.Log
|
||||
import androidx.room.Dao
|
||||
@ -9,11 +9,9 @@ import androidx.room.PrimaryKey
|
||||
import androidx.room.Query
|
||||
import androidx.room.TypeConverter
|
||||
import androidx.room.TypeConverters
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@Entity
|
||||
@TypeConverters(StringListTypeConverter::class)
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.LiveData
|
||||
@ -225,7 +225,7 @@ interface SavedItemDao {
|
||||
excludedLabels: List<String>,
|
||||
allowedContentReaders: List<String>
|
||||
): LiveData<List<SavedItemWithLabelsAndHighlights>> {
|
||||
val result = _filteredLibraryData(
|
||||
return _filteredLibraryData(
|
||||
allowedArchiveStates = allowedArchiveStates,
|
||||
sortKey = sortKey,
|
||||
hasRequiredLabels = requiredLabels.size,
|
||||
@ -234,7 +234,6 @@ interface SavedItemDao {
|
||||
excludedLabels = excludedLabels,
|
||||
allowedContentReaders = allowedContentReaders
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.*
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
|
||||
@Entity
|
||||
data class SavedItemLabel(
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
@ -1,7 +1,6 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
package app.omnivore.omnivore.core.database.entities
|
||||
|
||||
import androidx.room.*
|
||||
import app.omnivore.omnivore.persistence.BaseDao
|
||||
|
||||
@Entity
|
||||
data class Viewer(
|
||||
@ -1,9 +1,11 @@
|
||||
package app.omnivore.omnivore
|
||||
package app.omnivore.omnivore.core.datastore
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.*
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import app.omnivore.omnivore.utils.Constants
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
@ -0,0 +1,10 @@
|
||||
package app.omnivore.omnivore.core.model
|
||||
|
||||
enum class ServerSyncStatus(val rawValue: Int) {
|
||||
IS_SYNCED(0),
|
||||
IS_SYNCING(1),
|
||||
NEEDS_DELETION(2),
|
||||
NEEDS_CREATION(3),
|
||||
NEEDS_UPDATE(4),
|
||||
NEEDS_MERGE(5)
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.graphql.generated.CreateHighlightMutation
|
||||
@ -10,7 +10,7 @@ import app.omnivore.omnivore.graphql.generated.type.CreateHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.HighlightType
|
||||
import app.omnivore.omnivore.graphql.generated.type.MergeHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdateHighlightInput
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.google.gson.Gson
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.Constants
|
||||
import app.omnivore.omnivore.DatastoreKeys
|
||||
import app.omnivore.omnivore.DatastoreRepository
|
||||
import app.omnivore.omnivore.utils.Constants
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import com.apollographql.apollo3.ApolloClient
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package app.omnivore.omnivore
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.graphql.generated.SaveArticleReadingProgressMutation
|
||||
import app.omnivore.omnivore.graphql.generated.type.SaveArticleReadingProgressInput
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.graphql.generated.CreateLabelMutation
|
||||
import app.omnivore.omnivore.graphql.generated.SetLabelsMutation
|
||||
@ -1,7 +1,7 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.graphql.generated.GetLabelsQuery
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
|
||||
|
||||
suspend fun Networker.savedItemLabels(): List<SavedItemLabel> {
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
@ -1,11 +1,11 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.graphql.generated.GetArticleQuery
|
||||
import app.omnivore.omnivore.graphql.generated.type.ContentReader
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.graphql.generated.UpdatesSinceQuery
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdateReason
|
||||
@ -1,8 +1,10 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.graphql.generated.SearchQuery
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.persistence.entities.*
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
|
||||
data class LibrarySearchQueryResponse(
|
||||
@ -1,7 +1,7 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.graphql.generated.TypeaheadSearchQuery
|
||||
import app.omnivore.omnivore.persistence.entities.TypeaheadCardData
|
||||
import app.omnivore.omnivore.core.database.entities.TypeaheadCardData
|
||||
|
||||
data class SearchQueryResponse(
|
||||
val cursor: String?,
|
||||
@ -1,7 +1,7 @@
|
||||
package app.omnivore.omnivore.network
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import app.omnivore.omnivore.graphql.generated.ViewerQuery
|
||||
import app.omnivore.omnivore.persistence.entities.Viewer
|
||||
import app.omnivore.omnivore.core.database.entities.Viewer
|
||||
|
||||
suspend fun Networker.viewer(): Viewer? {
|
||||
try {
|
||||
@ -1,8 +1,11 @@
|
||||
package app.omnivore.omnivore
|
||||
package app.omnivore.omnivore.di
|
||||
|
||||
import android.content.Context
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.core.analytics.EventTracker
|
||||
import app.omnivore.omnivore.core.datastore.OmnivoreDatastore
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@ -1,12 +1,12 @@
|
||||
package app.omnivore.omnivore.ui
|
||||
package app.omnivore.omnivore.feature
|
||||
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.SetLabelsInput
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import app.omnivore.omnivore.network.updateLabelsForSavedItem
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCrossRef
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.updateLabelsForSavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemAndSavedItemLabelCrossRef
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui
|
||||
package app.omnivore.omnivore.feature
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.net.Uri
|
||||
@ -17,7 +17,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import app.omnivore.omnivore.AppleConstants
|
||||
import app.omnivore.omnivore.utils.AppleConstants
|
||||
import app.omnivore.omnivore.R
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.widget.Toast
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.widget.Toast
|
||||
@ -27,7 +27,7 @@ import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.BuildConfig
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.ui.auth.AuthUtils.autofill
|
||||
import app.omnivore.omnivore.feature.auth.AuthUtils.autofill
|
||||
|
||||
@SuppressLint("CoroutineCreationDuringComposition")
|
||||
@Composable
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.widget.Toast
|
||||
@ -29,7 +29,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.ui.auth.AuthUtils.autofill
|
||||
import app.omnivore.omnivore.feature.auth.AuthUtils.autofill
|
||||
|
||||
@Composable
|
||||
fun EmailSignUpView(viewModel: LoginViewModel) {
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.clickable
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
@ -7,11 +7,26 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.*
|
||||
import app.omnivore.omnivore.*
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.core.analytics.EventTracker
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.core.network.AuthProviderLoginSubmit
|
||||
import app.omnivore.omnivore.core.network.CreateAccountParams
|
||||
import app.omnivore.omnivore.core.network.CreateAccountSubmit
|
||||
import app.omnivore.omnivore.core.network.CreateEmailAccountSubmit
|
||||
import app.omnivore.omnivore.core.network.EmailLoginCredentials
|
||||
import app.omnivore.omnivore.core.network.EmailLoginSubmit
|
||||
import app.omnivore.omnivore.core.network.EmailSignUpParams
|
||||
import app.omnivore.omnivore.graphql.generated.ValidateUsernameQuery
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import app.omnivore.omnivore.network.viewer
|
||||
import app.omnivore.omnivore.ui.ResourceProvider
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.PendingUserSubmit
|
||||
import app.omnivore.omnivore.core.network.RetrofitHelper
|
||||
import app.omnivore.omnivore.core.network.SignInParams
|
||||
import app.omnivore.omnivore.core.network.UserProfile
|
||||
import app.omnivore.omnivore.core.network.viewer
|
||||
import app.omnivore.omnivore.feature.ResourceProvider
|
||||
import app.omnivore.omnivore.utils.Constants
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import com.apollographql.apollo3.ApolloClient
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||
import com.google.android.gms.common.api.ApiException
|
||||
@ -1,13 +1,8 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
@ -19,22 +14,16 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.ContextCompat
|
||||
import app.omnivore.omnivore.BuildConfig
|
||||
import app.omnivore.omnivore.DatastoreKeys
|
||||
import app.omnivore.omnivore.R
|
||||
|
||||
@SuppressLint("CoroutineCreationDuringComposition")
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.auth
|
||||
package app.omnivore.omnivore.feature.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
@ -21,7 +21,7 @@ import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.ui.theme.OmnivoreTheme
|
||||
import app.omnivore.omnivore.feature.theme.OmnivoreTheme
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.google.android.gms.common.GoogleApiAvailability
|
||||
import kotlinx.coroutines.launch
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.*
|
||||
@ -18,14 +18,13 @@ import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.ui.save.SaveState
|
||||
import app.omnivore.omnivore.ui.save.SaveViewModel
|
||||
import app.omnivore.omnivore.feature.save.SaveState
|
||||
import app.omnivore.omnivore.feature.save.SaveViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
enum class HighlightColorPaletteMode(val backgroundColor: Color) {
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
@ -0,0 +1,47 @@
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LabelFilterChip(
|
||||
onClick: () -> Unit,
|
||||
label: String
|
||||
) {
|
||||
var selected by remember { mutableStateOf(false) }
|
||||
|
||||
FilterChip(
|
||||
onClick = {
|
||||
selected = !selected
|
||||
onClick()
|
||||
},
|
||||
label = {
|
||||
Text(label)
|
||||
},
|
||||
selected = selected,
|
||||
leadingIcon = if (selected) {
|
||||
{
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Done,
|
||||
contentDescription = "Done icon",
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LabelsSelectionSheetContent2(
|
||||
isLibraryMode: Boolean,
|
||||
labels: List<SavedItemLabel>,
|
||||
initialSelectedLabels: List<SavedItemLabel>,
|
||||
labelsViewModel: LabelsViewModel,
|
||||
onCancel: () -> Unit,
|
||||
onSave: (List<SavedItemLabel>) -> Unit,
|
||||
onCreateLabel: (String, String) -> Unit
|
||||
) {
|
||||
// Use mutableStateMapOf for more idiomatic management of collection state
|
||||
val selectedLabels = remember {
|
||||
mutableStateMapOf<SavedItemLabel, Boolean>().apply {
|
||||
initialSelectedLabels.forEach {
|
||||
put(
|
||||
it,
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
var newLabelName by remember { mutableStateOf("") }
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = if (isLibraryMode) stringResource(R.string.label_selection_sheet_title) else
|
||||
stringResource(R.string.label_selection_sheet_title_alt)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onCancel) {
|
||||
Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back")
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = { onSave(selectedLabels.filter { it.value }.keys.toList()) }) {
|
||||
Text(
|
||||
text = if (isLibraryMode)
|
||||
stringResource(R.string.label_selection_sheet_action_search) else
|
||||
stringResource(R.string.label_selection_sheet_action_save)
|
||||
)
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.background
|
||||
)
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.Start
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = newLabelName,
|
||||
onValueChange = { newLabelName = it },
|
||||
label = { Text("New Label Name") },
|
||||
singleLine = true,
|
||||
trailingIcon = {
|
||||
IconButton(onClick = {
|
||||
val labelHexValue = "#FFFFFF"
|
||||
onCreateLabel(newLabelName, labelHexValue)
|
||||
newLabelName = ""
|
||||
}) {
|
||||
Icon(Icons.Filled.Add, contentDescription = "Create Label")
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)
|
||||
)
|
||||
Row {
|
||||
labels.forEach { label ->
|
||||
FilterChip(
|
||||
selected = selectedLabels[label] ?: false,
|
||||
onClick = {
|
||||
selectedLabels[label] = !(selectedLabels[label] ?: false)
|
||||
},
|
||||
label = { Text(label.name) },
|
||||
leadingIcon = if (selectedLabels[label] == true) {
|
||||
{
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Check,
|
||||
contentDescription = "Selected",
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
modifier = Modifier.padding(8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
@file:OptIn(ExperimentalMaterialApi::class)
|
||||
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.Canvas
|
||||
@ -8,7 +8,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@ -25,17 +24,12 @@ import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AddCircle
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SmallTopAppBar
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
@ -58,20 +52,18 @@ import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.platform.ViewConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
import androidx.compose.ui.text.toLowerCase
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import com.dokar.chiptextfield.Chip
|
||||
import com.dokar.chiptextfield.ChipTextField
|
||||
import com.dokar.chiptextfield.ChipTextFieldDefaults
|
||||
import com.dokar.chiptextfield.ChipTextFieldState
|
||||
import com.dokar.chiptextfield.m3.ChipTextField
|
||||
import com.dokar.chiptextfield.m3.ChipTextFieldDefaults
|
||||
import com.dokar.chiptextfield.rememberChipTextFieldState
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneOffset
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.components
|
||||
package app.omnivore.omnivore.feature.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.editinfo
|
||||
package app.omnivore.omnivore.feature.editinfo
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.*
|
||||
@ -11,7 +11,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.editinfo
|
||||
package app.omnivore.omnivore.feature.editinfo
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@ -6,14 +6,14 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.omnivore.omnivore.Constants
|
||||
import app.omnivore.omnivore.DatastoreKeys
|
||||
import app.omnivore.omnivore.DatastoreRepository
|
||||
import app.omnivore.omnivore.utils.Constants
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.graphql.generated.UpdatePageMutation
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdatePageInput
|
||||
import app.omnivore.omnivore.ui.ResourceProvider
|
||||
import app.omnivore.omnivore.feature.ResourceProvider
|
||||
import com.apollographql.apollo3.ApolloClient
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
enum class LibraryBottomSheetState {
|
||||
HIDDEN,
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
@ -17,8 +17,8 @@ import androidx.compose.ui.text.intl.Locale
|
||||
import androidx.compose.ui.text.toLowerCase
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.ui.components.LabelChipColors
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.feature.components.LabelChipColors
|
||||
|
||||
@Composable
|
||||
fun LibraryFilterBar(viewModel: LibraryViewModel) {
|
||||
@ -0,0 +1,234 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.navigation.NavHostController
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LibraryNavigationBar(
|
||||
savedItemViewModel: SavedItemViewModel,
|
||||
onSearchClicked: () -> Unit,
|
||||
onAddLinkClicked: () -> Unit,
|
||||
onSettingsIconClick: () -> Unit
|
||||
) {
|
||||
val actionsMenuItem: SavedItemWithLabelsAndHighlights? by savedItemViewModel.actionsMenuItemLiveData.observeAsState(
|
||||
null
|
||||
)
|
||||
|
||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
if (actionsMenuItem == null)
|
||||
stringResource(R.string.library_nav_bar_title) else
|
||||
stringResource(R.string.library_nav_bar_title_alt)
|
||||
)
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = if (actionsMenuItem == null) MaterialTheme.colorScheme.background else MaterialTheme.colorScheme.surfaceVariant
|
||||
),
|
||||
navigationIcon = {
|
||||
if (actionsMenuItem != null) {
|
||||
IconButton(onClick = {
|
||||
savedItemViewModel.actionsMenuItemLiveData.postValue(null)
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
modifier = Modifier,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
actionsMenuItem?.let {
|
||||
IconButton(onClick = {
|
||||
savedItemViewModel.handleSavedItemAction(
|
||||
it.savedItem.savedItemId,
|
||||
if (it.savedItem.isArchived) SavedItemAction.Unarchive else SavedItemAction.Archive
|
||||
)
|
||||
}) {
|
||||
if (it.savedItem.isArchived) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.unarchive),
|
||||
contentDescription = null
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.archive_outline),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
IconButton(onClick = {
|
||||
savedItemViewModel.handleSavedItemAction(
|
||||
it.savedItem.savedItemId,
|
||||
SavedItemAction.EditInfo
|
||||
)
|
||||
}) {
|
||||
Icon(
|
||||
Icons.Outlined.Info,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = {
|
||||
savedItemViewModel.handleSavedItemAction(
|
||||
it.savedItem.savedItemId,
|
||||
SavedItemAction.EditLabels
|
||||
)
|
||||
}) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tag),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = {
|
||||
savedItemViewModel.handleSavedItemAction(
|
||||
it.savedItem.savedItemId,
|
||||
SavedItemAction.Delete
|
||||
)
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Delete,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { isMenuExpanded = true } ) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
if (isMenuExpanded) {
|
||||
SavedItemLibraryContextMenu(
|
||||
savedItemViewModel = savedItemViewModel,
|
||||
savedItem = it.savedItem,
|
||||
isExpanded = true,
|
||||
onDismiss = { isMenuExpanded = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: run {
|
||||
IconButton(onClick = onSearchClicked) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Search,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(onClick = onAddLinkClicked) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Add,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(onClick = onSettingsIconClick) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SearchField(
|
||||
searchText: String,
|
||||
onSearch: () -> Unit,
|
||||
onSearchTextChanged: (String) -> Unit,
|
||||
navController: NavHostController,
|
||||
) {
|
||||
var showClearButton by remember { mutableStateOf(false) }
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onFocusChanged { focusState ->
|
||||
showClearButton = (focusState.isFocused)
|
||||
}
|
||||
.focusRequester(focusRequester),
|
||||
value = searchText,
|
||||
onValueChange = onSearchTextChanged,
|
||||
placeholder = {
|
||||
Text(text = stringResource(R.string.library_nav_bar_field_placeholder_search))
|
||||
},
|
||||
leadingIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
onSearchTextChanged("")
|
||||
navController.popBackStack()
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
},
|
||||
trailingIcon = {
|
||||
AnimatedVisibility(
|
||||
visible = showClearButton,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut()
|
||||
) {
|
||||
IconButton(onClick = { onSearchTextChanged("") }) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Close,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
maxLines = 1,
|
||||
singleLine = true,
|
||||
keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Search),
|
||||
keyboardActions = KeyboardActions(onSearch = {
|
||||
onSearch()
|
||||
}),
|
||||
)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
@ -53,19 +53,19 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import app.omnivore.omnivore.Routes
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.ui.components.AddLinkSheetContent
|
||||
import app.omnivore.omnivore.ui.components.LabelsSelectionSheetContent
|
||||
import app.omnivore.omnivore.ui.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.ui.editinfo.EditInfoSheetContent
|
||||
import app.omnivore.omnivore.ui.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.ui.reader.PDFReaderActivity
|
||||
import app.omnivore.omnivore.ui.reader.WebReaderLoadingContainerActivity
|
||||
import app.omnivore.omnivore.ui.save.SaveState
|
||||
import app.omnivore.omnivore.ui.save.SaveViewModel
|
||||
import app.omnivore.omnivore.ui.savedItemViews.SavedItemCard
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.feature.components.AddLinkSheetContent
|
||||
import app.omnivore.omnivore.feature.components.LabelsSelectionSheetContent
|
||||
import app.omnivore.omnivore.feature.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.feature.editinfo.EditInfoSheetContent
|
||||
import app.omnivore.omnivore.feature.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.feature.reader.PDFReaderActivity
|
||||
import app.omnivore.omnivore.feature.reader.WebReaderLoadingContainerActivity
|
||||
import app.omnivore.omnivore.feature.save.SaveState
|
||||
import app.omnivore.omnivore.feature.save.SaveViewModel
|
||||
import app.omnivore.omnivore.feature.savedItemViews.SavedItemCard
|
||||
import app.omnivore.omnivore.navigation.Routes
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@ -7,27 +7,27 @@ import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.omnivore.omnivore.DatastoreKeys
|
||||
import app.omnivore.omnivore.DatastoreRepository
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.dataService.archiveSavedItem
|
||||
import app.omnivore.omnivore.dataService.deleteSavedItem
|
||||
import app.omnivore.omnivore.dataService.fetchSavedItemContent
|
||||
import app.omnivore.omnivore.dataService.isSavedItemContentStoredInDB
|
||||
import app.omnivore.omnivore.dataService.librarySearch
|
||||
import app.omnivore.omnivore.dataService.sync
|
||||
import app.omnivore.omnivore.dataService.syncLabels
|
||||
import app.omnivore.omnivore.dataService.syncOfflineItemsWithServerIfNeeded
|
||||
import app.omnivore.omnivore.dataService.unarchiveSavedItem
|
||||
import app.omnivore.omnivore.dataService.updateWebReadingProgress
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.data.archiveSavedItem
|
||||
import app.omnivore.omnivore.core.data.deleteSavedItem
|
||||
import app.omnivore.omnivore.core.data.fetchSavedItemContent
|
||||
import app.omnivore.omnivore.core.data.isSavedItemContentStoredInDB
|
||||
import app.omnivore.omnivore.core.data.librarySearch
|
||||
import app.omnivore.omnivore.core.data.sync
|
||||
import app.omnivore.omnivore.core.data.syncLabels
|
||||
import app.omnivore.omnivore.core.data.syncOfflineItemsWithServerIfNeeded
|
||||
import app.omnivore.omnivore.core.data.unarchiveSavedItem
|
||||
import app.omnivore.omnivore.core.data.updateWebReadingProgress
|
||||
import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import app.omnivore.omnivore.network.createNewLabel
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.ui.ResourceProvider
|
||||
import app.omnivore.omnivore.ui.setSavedItemLabels
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.createNewLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.feature.ResourceProvider
|
||||
import app.omnivore.omnivore.feature.setSavedItemLabels
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@ -198,12 +198,6 @@ class LibraryViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
// fun sortKey(appliedSortKey: String) {
|
||||
// when(appliedSortKey) {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun handleFilterChanges() {
|
||||
librarySearchCursor = null
|
||||
|
||||
@ -344,6 +338,20 @@ class LibraryViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SavedItemAction.MarkUnread -> {
|
||||
viewModelScope.launch {
|
||||
dataService.updateWebReadingProgress(
|
||||
jsonString = Gson().toJson(
|
||||
mapOf(
|
||||
"id" to itemID,
|
||||
"readingProgressPercent" to 0,
|
||||
"readingProgressAnchorIndex" to 0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
actionsMenuItemLiveData.postValue(null)
|
||||
}
|
||||
@ -442,5 +450,6 @@ enum class SavedItemAction {
|
||||
Unarchive,
|
||||
EditLabels,
|
||||
EditInfo,
|
||||
MarkRead
|
||||
MarkRead,
|
||||
MarkUnread
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
@ -0,0 +1,48 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
|
||||
@Composable
|
||||
fun SavedItemLibraryContextMenu(
|
||||
savedItemViewModel: SavedItemViewModel,
|
||||
savedItem: SavedItem,
|
||||
isExpanded: Boolean,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val menuOptions = listOf(
|
||||
if (savedItemViewModel.actionsMenuItemLiveData.value?.savedItem?.readingProgress == 100.0) {
|
||||
MenuItemOption(R.string.saved_item_context_menu_action_mark_unread, SavedItemAction.MarkUnread)
|
||||
} else {
|
||||
MenuItemOption(R.string.saved_item_context_menu_action_mark_read, SavedItemAction.MarkRead)
|
||||
}
|
||||
)
|
||||
|
||||
DropdownMenu(
|
||||
expanded = isExpanded,
|
||||
onDismissRequest = onDismiss
|
||||
) {
|
||||
menuOptions.forEach { option ->
|
||||
DropdownMenuItem(
|
||||
text = { Text( text = stringResource(option.textResourceId), fontWeight = FontWeight.Normal) },
|
||||
onClick = {
|
||||
savedItemViewModel.handleSavedItemAction(savedItem.savedItemId, option.action)
|
||||
onDismiss()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MenuItemOption(
|
||||
val textResourceId: Int,
|
||||
val action: SavedItemAction,
|
||||
val customAction: (() -> Unit)? = null
|
||||
)
|
||||
@ -0,0 +1,39 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
enum class SavedItemSortFilter(
|
||||
val displayText: String,
|
||||
val rawValue: String,
|
||||
val queryString: String
|
||||
) {
|
||||
NEWEST("Newest", rawValue = "newest", "sort:saved"),
|
||||
OLDEST("Oldest", rawValue = "oldest", "sort:saved-ASC"),
|
||||
RECENTLY_READ("Recently Read", rawValue = "recentlyRead", "sort:read"),
|
||||
RECENTLY_PUBLISHED("Recently Published", rawValue = "recentlyPublished", "sort:published"),
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SavedItemSortFilterContextMenu(
|
||||
isExpanded: Boolean,
|
||||
onDismiss: () -> Unit,
|
||||
actionHandler: (SavedItemSortFilter) -> Unit
|
||||
) {
|
||||
DropdownMenu(
|
||||
expanded = isExpanded,
|
||||
onDismissRequest = onDismiss
|
||||
) {
|
||||
SavedItemSortFilter.values().forEach {
|
||||
DropdownMenuItem(
|
||||
text = { Text(it.displayText) },
|
||||
onClick = {
|
||||
actionHandler(it)
|
||||
onDismiss()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
|
||||
interface SavedItemViewModel {
|
||||
|
||||
@ -0,0 +1,226 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.database.entities.TypeaheadCardData
|
||||
import app.omnivore.omnivore.feature.reader.PDFReaderActivity
|
||||
import app.omnivore.omnivore.feature.reader.WebReaderLoadingContainerActivity
|
||||
import app.omnivore.omnivore.feature.savedItemViews.SavedItemCard
|
||||
import app.omnivore.omnivore.feature.savedItemViews.TypeaheadSearchCard
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SearchView(
|
||||
viewModel: SearchViewModel,
|
||||
navController: NavHostController
|
||||
) {
|
||||
val isRefreshing: Boolean by viewModel.isRefreshing.observeAsState(false)
|
||||
val typeaheadMode: Boolean by viewModel.typeaheadMode.observeAsState(true)
|
||||
val searchText: String by viewModel.searchTextLiveData.observeAsState("")
|
||||
val actionsMenuItem: SavedItemWithLabelsAndHighlights? by viewModel.actionsMenuItemLiveData.observeAsState(
|
||||
null
|
||||
)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("") },
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceVariant
|
||||
),
|
||||
navigationIcon = {
|
||||
if (actionsMenuItem != null) {
|
||||
IconButton(onClick = {
|
||||
viewModel.actionsMenuItemLiveData.postValue(null)
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
modifier = Modifier,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if (actionsMenuItem != null) {
|
||||
IconButton(onClick = { }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.archive_outline),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tag),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { }) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Delete,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Row {
|
||||
SearchField(
|
||||
searchText,
|
||||
onSearch = {
|
||||
viewModel.performSearch()
|
||||
},
|
||||
onSearchTextChanged = { viewModel.updateSearchText(it) },
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
) { paddingValues ->
|
||||
if (isRefreshing) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.height(45.dp)
|
||||
.width(45.dp),
|
||||
strokeWidth = 5.dp,
|
||||
color = colorResource(R.color.green_55B938)
|
||||
)
|
||||
}
|
||||
} else if (typeaheadMode) {
|
||||
TypeaheadSearchViewContent(
|
||||
viewModel,
|
||||
modifier = Modifier
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
)
|
||||
} else {
|
||||
SearchViewContent(
|
||||
viewModel,
|
||||
modifier = Modifier
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TypeaheadSearchViewContent(viewModel: SearchViewModel, modifier: Modifier) {
|
||||
val context = LocalContext.current
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
val searchedCardsData: List<TypeaheadCardData> by viewModel.searchItemsLiveData.observeAsState(
|
||||
listOf()
|
||||
)
|
||||
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = modifier
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.fillMaxSize()
|
||||
|
||||
) {
|
||||
items(searchedCardsData) { cardData ->
|
||||
TypeaheadSearchCard(
|
||||
cardData = cardData,
|
||||
onClickHandler = {
|
||||
// val activityClass = if (cardData.isPDF()) PDFReaderActivity::class.java else WebReaderLoadingContainerActivity::class.java
|
||||
val activityClass = WebReaderLoadingContainerActivity::class.java
|
||||
val intent = Intent(context, activityClass)
|
||||
intent.putExtra("SAVED_ITEM_SLUG", cardData.slug)
|
||||
context.startActivity(intent)
|
||||
},
|
||||
actionHandler = { viewModel.handleSavedItemAction(cardData.savedItemId, it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SearchViewContent(viewModel: SearchViewModel, modifier: Modifier) {
|
||||
val context = LocalContext.current
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
val cardsData: List<SavedItemWithLabelsAndHighlights> by viewModel.itemsLiveData.observeAsState(
|
||||
listOf()
|
||||
)
|
||||
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = modifier
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.fillMaxSize()
|
||||
|
||||
) {
|
||||
items(cardsData) { cardDataWithLabels ->
|
||||
SavedItemCard(
|
||||
selected = false,
|
||||
savedItemViewModel = viewModel,
|
||||
savedItem = cardDataWithLabels,
|
||||
onClickHandler = {
|
||||
val activityClass =
|
||||
if (cardDataWithLabels.savedItem.contentReader == "PDF") PDFReaderActivity::class.java else WebReaderLoadingContainerActivity::class.java
|
||||
val intent = Intent(context, activityClass)
|
||||
intent.putExtra("SAVED_ITEM_SLUG", cardDataWithLabels.savedItem.slug)
|
||||
context.startActivity(intent)
|
||||
},
|
||||
actionHandler = {
|
||||
viewModel.handleSavedItemAction(
|
||||
cardDataWithLabels.savedItem.savedItemId,
|
||||
it
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,16 +1,27 @@
|
||||
package app.omnivore.omnivore.ui.library
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.omnivore.omnivore.*
|
||||
import app.omnivore.omnivore.dataService.*
|
||||
import app.omnivore.omnivore.network.*
|
||||
import app.omnivore.omnivore.persistence.entities.*
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.data.archiveSavedItem
|
||||
import app.omnivore.omnivore.core.data.deleteSavedItem
|
||||
import app.omnivore.omnivore.core.data.isSavedItemContentStoredInDB
|
||||
import app.omnivore.omnivore.core.data.librarySearch
|
||||
import app.omnivore.omnivore.core.data.unarchiveSavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.database.entities.TypeaheadCardData
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.typeaheadSearch
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@ -18,7 +29,7 @@ class SearchViewModel @Inject constructor(
|
||||
private val networker: Networker,
|
||||
private val dataService: DataService,
|
||||
private val datastoreRepo: DatastoreRepository
|
||||
): ViewModel(), SavedItemViewModel {
|
||||
) : ViewModel(), SavedItemViewModel {
|
||||
private val contentRequestChannel = Channel<String>(capacity = Channel.UNLIMITED)
|
||||
|
||||
private var cursor: String? = null
|
||||
@ -66,7 +77,10 @@ class SearchViewModel @Inject constructor(
|
||||
private fun loadUsingSearchAPI() {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val result = dataService.librarySearch(cursor = librarySearchCursor, query = searchQueryString())
|
||||
val result = dataService.librarySearch(
|
||||
cursor = librarySearchCursor,
|
||||
query = searchQueryString()
|
||||
)
|
||||
result.cursor?.let {
|
||||
librarySearchCursor = it
|
||||
}
|
||||
@ -81,29 +95,29 @@ class SearchViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
val newItems = result.savedItems
|
||||
/*
|
||||
.map {
|
||||
SavedItemCardDataWithLabels(
|
||||
cardData = SavedItemCardData(
|
||||
savedItemId = it.savedItem.savedItemId,
|
||||
slug = it.savedItem.slug,
|
||||
publisherURLString = it.savedItem.publisherURLString,
|
||||
title = it.savedItem.title,
|
||||
author = it.savedItem.author,
|
||||
imageURLString = it.savedItem.imageURLString,
|
||||
isArchived = it.savedItem.isArchived,
|
||||
pageURLString = it.savedItem.pageURLString,
|
||||
contentReader = it.savedItem.contentReader,
|
||||
savedAt = it.savedItem.savedAt,
|
||||
readingProgress = it.savedItem.readingProgress,
|
||||
wordsCount = it.savedItem.wordsCount
|
||||
),
|
||||
labels = listOf()
|
||||
)
|
||||
}
|
||||
*/
|
||||
/*
|
||||
.map {
|
||||
SavedItemCardDataWithLabels(
|
||||
cardData = SavedItemCardData(
|
||||
savedItemId = it.savedItem.savedItemId,
|
||||
slug = it.savedItem.slug,
|
||||
publisherURLString = it.savedItem.publisherURLString,
|
||||
title = it.savedItem.title,
|
||||
author = it.savedItem.author,
|
||||
imageURLString = it.savedItem.imageURLString,
|
||||
isArchived = it.savedItem.isArchived,
|
||||
pageURLString = it.savedItem.pageURLString,
|
||||
contentReader = it.savedItem.contentReader,
|
||||
savedAt = it.savedItem.savedAt,
|
||||
readingProgress = it.savedItem.readingProgress,
|
||||
wordsCount = it.savedItem.wordsCount
|
||||
),
|
||||
labels = listOf()
|
||||
)
|
||||
}
|
||||
*/
|
||||
|
||||
itemsLiveData.value?.let{
|
||||
itemsLiveData.value?.let {
|
||||
itemsLiveData.postValue(newItems + it)
|
||||
} ?: run {
|
||||
itemsLiveData.postValue(newItems)
|
||||
@ -146,24 +160,29 @@ class SearchViewModel @Inject constructor(
|
||||
dataService.deleteSavedItem(itemID)
|
||||
}
|
||||
}
|
||||
|
||||
SavedItemAction.Archive -> {
|
||||
viewModelScope.launch {
|
||||
dataService.archiveSavedItem(itemID)
|
||||
}
|
||||
}
|
||||
|
||||
SavedItemAction.Unarchive -> {
|
||||
viewModelScope.launch {
|
||||
dataService.unarchiveSavedItem(itemID)
|
||||
}
|
||||
}
|
||||
|
||||
SavedItemAction.EditLabels -> {
|
||||
// TODO
|
||||
}
|
||||
|
||||
SavedItemAction.EditInfo -> {
|
||||
// TODO
|
||||
}
|
||||
|
||||
SavedItemAction.MarkRead -> TODO()
|
||||
SavedItemAction.MarkUnread -> TODO()
|
||||
}
|
||||
actionsMenuItemLiveData.postValue(null)
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.notebook
|
||||
package app.omnivore.omnivore.feature.notebook
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
@ -6,7 +6,6 @@ import android.content.Context
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
@ -36,11 +35,11 @@ import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import dev.jeziellago.compose.markdowntext.MarkdownText
|
||||
import kotlinx.coroutines.launch
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.ui.theme.OmnivoreTheme
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.feature.theme.OmnivoreTheme
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package app.omnivore.omnivore.ui.notebook
|
||||
package app.omnivore.omnivore.feature.notebook
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.dataService.createNoteHighlight
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.data.createNoteHighlight
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdateHighlightInput
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import app.omnivore.omnivore.network.updateHighlight
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.updateHighlight
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
@ -9,8 +9,8 @@ import android.view.WindowManager
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import app.omnivore.omnivore.ui.notebook.EditNoteModal
|
||||
import app.omnivore.omnivore.ui.theme.OmnivoreTheme
|
||||
import app.omnivore.omnivore.feature.notebook.EditNoteModal
|
||||
import app.omnivore.omnivore.feature.theme.OmnivoreTheme
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipData
|
||||
@ -19,7 +19,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import com.pspdfkit.annotations.Annotation
|
||||
import com.pspdfkit.annotations.HighlightAnnotation
|
||||
import com.pspdfkit.configuration.PdfConfiguration
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
@ -6,13 +6,20 @@ import android.util.Log
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.dataService.NanoId
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.ReadingProgressParams
|
||||
import app.omnivore.omnivore.core.network.createHighlight
|
||||
import app.omnivore.omnivore.core.network.deleteHighlights
|
||||
import app.omnivore.omnivore.core.network.mergeHighlights
|
||||
import app.omnivore.omnivore.core.network.savedItem
|
||||
import app.omnivore.omnivore.core.network.updateHighlight
|
||||
import app.omnivore.omnivore.core.network.updateReadingProgress
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.data.NanoId
|
||||
import app.omnivore.omnivore.graphql.generated.type.CreateHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.MergeHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdateHighlightInput
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import app.omnivore.omnivore.network.*
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.google.gson.Gson
|
||||
import com.pspdfkit.annotations.Annotation
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
@ -24,7 +24,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.ui.theme.OmnivoreTheme
|
||||
import app.omnivore.omnivore.feature.theme.OmnivoreTheme
|
||||
|
||||
@Composable
|
||||
fun ReaderPreferencesView(webReaderViewModel: WebReaderViewModel) {
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipData
|
||||
@ -1,8 +1,8 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import com.google.gson.Gson
|
||||
|
||||
enum class WebFont(val displayText: String, val rawValue: String) {
|
||||
@ -0,0 +1,528 @@
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ModalBottomSheetLayout
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.TopAppBar
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import app.omnivore.omnivore.MainActivity
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.feature.components.LabelsSelectionSheetContent2
|
||||
import app.omnivore.omnivore.feature.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.feature.editinfo.EditInfoSheetContent
|
||||
import app.omnivore.omnivore.feature.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.feature.notebook.EditNoteModal
|
||||
import app.omnivore.omnivore.feature.notebook.NotebookView
|
||||
import app.omnivore.omnivore.feature.notebook.NotebookViewModel
|
||||
import app.omnivore.omnivore.feature.savedItemViews.SavedItemContextMenu
|
||||
import app.omnivore.omnivore.feature.theme.OmnivoreTheme
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@AndroidEntryPoint
|
||||
class WebReaderLoadingContainerActivity : ComponentActivity() {
|
||||
val viewModel: WebReaderViewModel by viewModels()
|
||||
private val notebookViewModel: NotebookViewModel by viewModels()
|
||||
private val labelsViewModel: LabelsViewModel by viewModels()
|
||||
private val editInfoViewModel: EditInfoViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val requestID = intent.getStringExtra("SAVED_ITEM_REQUEST_ID")
|
||||
val slug = intent.getStringExtra("SAVED_ITEM_SLUG")
|
||||
|
||||
viewModel.loadItem(slug = slug, requestID = requestID)
|
||||
|
||||
setContent {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val useDarkIcons = !isSystemInDarkTheme()
|
||||
|
||||
DisposableEffect(systemUiController, useDarkIcons) {
|
||||
systemUiController.setSystemBarsColor(
|
||||
color = Color.Black,
|
||||
darkIcons = false
|
||||
)
|
||||
|
||||
onDispose {}
|
||||
}
|
||||
|
||||
OmnivoreTheme {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(color = Color.Black)
|
||||
) {
|
||||
if (viewModel.hasFetchError.value == true) {
|
||||
Text(stringResource(R.string.web_reader_loading_container_error_msg))
|
||||
} else {
|
||||
WebReaderLoadingContainer(
|
||||
onLibraryIconTap = if (requestID != null) {
|
||||
{ startMainActivity() }
|
||||
} else null,
|
||||
webReaderViewModel = viewModel,
|
||||
notebookViewModel = notebookViewModel,
|
||||
labelsViewModel = labelsViewModel,
|
||||
editInfoViewModel = editInfoViewModel,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// animate the view up when keyboard appears
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
val rootView = findViewById<View>(android.R.id.content).rootView
|
||||
ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, insets ->
|
||||
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
||||
rootView.setPadding(0, 0, 0, imeHeight)
|
||||
insets
|
||||
}
|
||||
}
|
||||
|
||||
private fun startMainActivity() {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
this.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
enum class BottomSheetState {
|
||||
NONE,
|
||||
PREFERENCES,
|
||||
NOTEBOOK,
|
||||
EDITNOTE,
|
||||
HIGHLIGHTNOTE,
|
||||
LABELS,
|
||||
LINK,
|
||||
EDIT_INFO,
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun WebReaderLoadingContainer(
|
||||
onLibraryIconTap: (() -> Unit)? = null,
|
||||
webReaderViewModel: WebReaderViewModel,
|
||||
notebookViewModel: NotebookViewModel,
|
||||
labelsViewModel: LabelsViewModel,
|
||||
editInfoViewModel: EditInfoViewModel
|
||||
) {
|
||||
val currentThemeKey = webReaderViewModel.currentThemeKey.observeAsState()
|
||||
val currentTheme = Themes.values().find { it.themeKey == currentThemeKey.value }
|
||||
val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
|
||||
val bottomSheetState: BottomSheetState? by webReaderViewModel.bottomSheetStateLiveData.observeAsState(
|
||||
BottomSheetState.NONE
|
||||
)
|
||||
|
||||
val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsLiveData.observeAsState(
|
||||
null
|
||||
)
|
||||
val shouldPopView: Boolean by webReaderViewModel.shouldPopViewLiveData.observeAsState(false)
|
||||
|
||||
val labels: List<SavedItemLabel> by webReaderViewModel.savedItemLabelsLiveData.observeAsState(
|
||||
listOf()
|
||||
)
|
||||
|
||||
val maxToolbarHeight = 48.dp
|
||||
webReaderViewModel.maxToolbarHeightPx =
|
||||
with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() }
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val styledContent = webReaderParams?.let {
|
||||
val webReaderContent = WebReaderContent(
|
||||
preferences = webReaderViewModel.storedWebPreferences(isSystemInDarkTheme()),
|
||||
item = it.item,
|
||||
articleContent = it.articleContent,
|
||||
)
|
||||
webReaderContent.styledContent()
|
||||
}
|
||||
|
||||
|
||||
val modalBottomSheetState = rememberModalBottomSheetState(
|
||||
initialValue = ModalBottomSheetValue.Hidden,
|
||||
skipHalfExpanded = bottomSheetState == BottomSheetState.EDITNOTE || bottomSheetState == BottomSheetState.HIGHLIGHTNOTE,
|
||||
confirmValueChange = {
|
||||
if (it == ModalBottomSheetValue.Hidden) {
|
||||
webReaderViewModel.resetBottomSheet()
|
||||
}
|
||||
true
|
||||
}
|
||||
)
|
||||
|
||||
val showMenu = {
|
||||
coroutineScope.launch {
|
||||
modalBottomSheetState.show()
|
||||
}
|
||||
}
|
||||
|
||||
when (bottomSheetState) {
|
||||
BottomSheetState.PREFERENCES -> {
|
||||
coroutineScope.launch {
|
||||
if (!modalBottomSheetState.isVisible) {
|
||||
modalBottomSheetState.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.NOTEBOOK, BottomSheetState.EDITNOTE,
|
||||
BottomSheetState.HIGHLIGHTNOTE, BottomSheetState.LABELS, BottomSheetState.EDIT_INFO,
|
||||
BottomSheetState.LINK,
|
||||
-> {
|
||||
showMenu()
|
||||
}
|
||||
|
||||
else -> {
|
||||
coroutineScope.launch {
|
||||
modalBottomSheetState.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModalBottomSheetLayout(
|
||||
modifier = Modifier
|
||||
.statusBarsPadding(),
|
||||
sheetBackgroundColor = Color.Transparent,
|
||||
sheetState = modalBottomSheetState,
|
||||
sheetContent = {
|
||||
when (bottomSheetState) {
|
||||
BottomSheetState.PREFERENCES -> {
|
||||
BottomSheetUI {
|
||||
ReaderPreferencesView(webReaderViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.NOTEBOOK -> {
|
||||
webReaderParams?.let { params ->
|
||||
BottomSheetUI {
|
||||
NotebookView(
|
||||
savedItemId = params.item.savedItemId,
|
||||
viewModel = notebookViewModel,
|
||||
onEditNote = {
|
||||
notebookViewModel.highlightUnderEdit = it
|
||||
webReaderViewModel.setBottomSheet(BottomSheetState.EDITNOTE)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.EDITNOTE -> {
|
||||
webReaderParams?.let { params ->
|
||||
EditNoteModal(
|
||||
initialValue = notebookViewModel.highlightUnderEdit?.annotation,
|
||||
onDismiss = { save, note ->
|
||||
coroutineScope.launch {
|
||||
if (save) {
|
||||
notebookViewModel.highlightUnderEdit?.let { highlight ->
|
||||
notebookViewModel.updateHighlightNote(
|
||||
highlight.highlightId,
|
||||
note
|
||||
)
|
||||
} ?: run {
|
||||
if (note != null) {
|
||||
notebookViewModel.addArticleNote(
|
||||
savedItemId = params.item.savedItemId,
|
||||
note = note
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
notebookViewModel.highlightUnderEdit = null
|
||||
}
|
||||
webReaderViewModel.setBottomSheet(BottomSheetState.NOTEBOOK)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.HIGHLIGHTNOTE -> {
|
||||
EditNoteModal(
|
||||
initialValue = webReaderViewModel.annotation,
|
||||
onDismiss = { save, note ->
|
||||
coroutineScope.launch {
|
||||
if (save) {
|
||||
webReaderViewModel.saveAnnotation(note ?: "")
|
||||
} else {
|
||||
webReaderViewModel.cancelAnnotation()
|
||||
}
|
||||
webReaderViewModel.annotation = null
|
||||
}
|
||||
webReaderViewModel.resetBottomSheet()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
BottomSheetState.LABELS -> {
|
||||
BottomSheetUI {
|
||||
LabelsSelectionSheetContent2(
|
||||
labels = labels,
|
||||
labelsViewModel = labelsViewModel,
|
||||
initialSelectedLabels = webReaderParams?.labels ?: listOf(),
|
||||
onCancel = {
|
||||
coroutineScope.launch {
|
||||
webReaderViewModel.resetBottomSheet()
|
||||
}
|
||||
},
|
||||
isLibraryMode = false,
|
||||
onSave = {
|
||||
if (it != labels) {
|
||||
webReaderViewModel.updateSavedItemLabels(
|
||||
savedItemID = webReaderParams?.item?.savedItemId ?: "",
|
||||
labels = it
|
||||
)
|
||||
}
|
||||
coroutineScope.launch {
|
||||
webReaderViewModel.resetBottomSheet()
|
||||
}
|
||||
},
|
||||
onCreateLabel = { newLabelName, labelHexValue ->
|
||||
webReaderViewModel.createNewSavedItemLabel(
|
||||
newLabelName,
|
||||
labelHexValue
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.EDIT_INFO -> {
|
||||
BottomSheetUI {
|
||||
EditInfoSheetContent(
|
||||
savedItemId = webReaderParams?.item?.savedItemId,
|
||||
title = webReaderParams?.item?.title,
|
||||
author = webReaderParams?.item?.author,
|
||||
description = webReaderParams?.item?.descriptionText,
|
||||
viewModel = editInfoViewModel,
|
||||
onCancel = {
|
||||
coroutineScope.launch {
|
||||
webReaderViewModel.resetBottomSheet()
|
||||
}
|
||||
},
|
||||
onUpdated = {
|
||||
coroutineScope.launch {
|
||||
webReaderViewModel.updateItemTitle()
|
||||
webReaderViewModel.resetBottomSheet()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.LINK -> {
|
||||
BottomSheetUI {
|
||||
OpenLinkView(webReaderViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetState.NONE -> {
|
||||
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1.0F))
|
||||
}
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
ReaderTopAppBar(webReaderViewModel, onLibraryIconTap)
|
||||
}) { paddingValues ->
|
||||
if (styledContent != null) {
|
||||
WebReader(
|
||||
styledContent = styledContent,
|
||||
webReaderViewModel = webReaderViewModel,
|
||||
currentTheme = currentTheme,
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(shouldPopView) {
|
||||
if (shouldPopView) {
|
||||
onBackPressedDispatcher?.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ReaderTopAppBar(
|
||||
webReaderViewModel: WebReaderViewModel,
|
||||
onLibraryIconTap: (() -> Unit)? = null
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
|
||||
|
||||
val isDarkMode = isSystemInDarkTheme()
|
||||
val currentThemeKey = webReaderViewModel.currentThemeKey.observeAsState()
|
||||
val currentTheme = Themes.values().find { it.themeKey == currentThemeKey.value }
|
||||
val toolbarHeightPx: Float by webReaderViewModel.currentToolbarHeightLiveData.observeAsState(
|
||||
0.0f
|
||||
)
|
||||
val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsLiveData.observeAsState(
|
||||
null
|
||||
)
|
||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||
|
||||
val themeBackgroundColor = currentTheme?.let {
|
||||
if (it.themeKey == "System" && isDarkMode) {
|
||||
Color(0xFF000000)
|
||||
} else if (it.themeKey == "System") {
|
||||
Color(0xFFFFFFFF)
|
||||
} else {
|
||||
Color(it.backgroundColor)
|
||||
}
|
||||
} ?: Color(0xFFFFFFFF)
|
||||
|
||||
val themeTintColor = currentTheme?.let {
|
||||
if (it.themeKey == "System" && isDarkMode) {
|
||||
Color(0xFFFFFFFF)
|
||||
} else if (it.themeKey == "System") {
|
||||
Color(0xFF000000)
|
||||
} else {
|
||||
Color(it.foregroundColor)
|
||||
}
|
||||
} ?: Color(0xFF000000)
|
||||
|
||||
|
||||
TopAppBar(
|
||||
modifier = Modifier
|
||||
.height(height = with(LocalDensity.current) {
|
||||
toolbarHeightPx.roundToInt().toDp()
|
||||
}),
|
||||
backgroundColor = themeBackgroundColor,
|
||||
elevation = 0.dp,
|
||||
title = {},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
onBackPressedDispatcher?.onBackPressed()
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
modifier = Modifier,
|
||||
contentDescription = "Back",
|
||||
tint = themeTintColor
|
||||
)
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if (onLibraryIconTap != null) {
|
||||
IconButton(onClick = { onLibraryIconTap() }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Home,
|
||||
contentDescription = null,
|
||||
tint = themeTintColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
webReaderParams?.let {
|
||||
IconButton(onClick = {
|
||||
webReaderViewModel.setBottomSheet(BottomSheetState.NOTEBOOK)
|
||||
}) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.notebook),
|
||||
contentDescription = null,
|
||||
tint = themeTintColor
|
||||
)
|
||||
}
|
||||
}
|
||||
IconButton(onClick = {
|
||||
webReaderViewModel.setBottomSheet(BottomSheetState.PREFERENCES)
|
||||
}) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.format_letter_case),
|
||||
contentDescription = null,
|
||||
tint = themeTintColor
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { isMenuExpanded = true }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.dots_horizontal),
|
||||
contentDescription = null,
|
||||
tint = themeTintColor
|
||||
)
|
||||
if (isMenuExpanded) {
|
||||
webReaderParams?.let { params ->
|
||||
SavedItemContextMenu(
|
||||
context = context,
|
||||
isExpanded = true,
|
||||
isArchived = params.item.isArchived,
|
||||
onDismiss = { isMenuExpanded = false },
|
||||
webReaderViewModel = webReaderViewModel,
|
||||
actionHandler = {
|
||||
webReaderViewModel.handleSavedItemAction(
|
||||
params.item.savedItemId,
|
||||
it
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BottomSheetUI(content: @Composable () -> Unit) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.wrapContentHeight()
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(topEnd = 20.dp, topStart = 20.dp))
|
||||
.background(Color.White)
|
||||
.statusBarsPadding()
|
||||
) {
|
||||
Scaffold { paddingValues ->
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.reader
|
||||
package app.omnivore.omnivore.feature.reader
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
@ -13,29 +13,29 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.omnivore.omnivore.DatastoreKeys
|
||||
import app.omnivore.omnivore.DatastoreRepository
|
||||
import app.omnivore.omnivore.EventTracker
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.core.analytics.EventTracker
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.dataService.DataService
|
||||
import app.omnivore.omnivore.dataService.archiveSavedItem
|
||||
import app.omnivore.omnivore.dataService.createWebHighlight
|
||||
import app.omnivore.omnivore.dataService.deleteHighlightFromJSON
|
||||
import app.omnivore.omnivore.dataService.deleteSavedItem
|
||||
import app.omnivore.omnivore.dataService.mergeWebHighlights
|
||||
import app.omnivore.omnivore.dataService.unarchiveSavedItem
|
||||
import app.omnivore.omnivore.dataService.updateWebHighlight
|
||||
import app.omnivore.omnivore.dataService.updateWebReadingProgress
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.data.archiveSavedItem
|
||||
import app.omnivore.omnivore.core.data.createWebHighlight
|
||||
import app.omnivore.omnivore.core.data.deleteHighlightFromJSON
|
||||
import app.omnivore.omnivore.core.data.deleteSavedItem
|
||||
import app.omnivore.omnivore.core.data.mergeWebHighlights
|
||||
import app.omnivore.omnivore.core.data.unarchiveSavedItem
|
||||
import app.omnivore.omnivore.core.data.updateWebHighlight
|
||||
import app.omnivore.omnivore.core.data.updateWebReadingProgress
|
||||
import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
|
||||
import app.omnivore.omnivore.network.Networker
|
||||
import app.omnivore.omnivore.network.createNewLabel
|
||||
import app.omnivore.omnivore.network.saveUrl
|
||||
import app.omnivore.omnivore.network.savedItem
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.ui.components.HighlightColor
|
||||
import app.omnivore.omnivore.ui.library.SavedItemAction
|
||||
import app.omnivore.omnivore.ui.setSavedItemLabels
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.createNewLabel
|
||||
import app.omnivore.omnivore.core.network.saveUrl
|
||||
import app.omnivore.omnivore.core.network.savedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.feature.components.HighlightColor
|
||||
import app.omnivore.omnivore.feature.library.SavedItemAction
|
||||
import app.omnivore.omnivore.feature.setSavedItemLabels
|
||||
import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@ -345,6 +345,20 @@ class WebReaderViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SavedItemAction.MarkUnread -> {
|
||||
viewModelScope.launch {
|
||||
dataService.updateWebReadingProgress(
|
||||
jsonString = Gson().toJson(
|
||||
mapOf(
|
||||
"id" to itemID,
|
||||
"readingProgressPercent" to 0,
|
||||
"readingProgressAnchorIndex" to 0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.root
|
||||
package app.omnivore.omnivore.feature.root
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -8,19 +8,19 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import app.omnivore.omnivore.Routes
|
||||
import app.omnivore.omnivore.ui.auth.LoginViewModel
|
||||
import app.omnivore.omnivore.ui.auth.WelcomeScreen
|
||||
import app.omnivore.omnivore.ui.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.ui.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.ui.library.LibraryView
|
||||
import app.omnivore.omnivore.ui.library.LibraryViewModel
|
||||
import app.omnivore.omnivore.ui.library.SearchView
|
||||
import app.omnivore.omnivore.ui.library.SearchViewModel
|
||||
import app.omnivore.omnivore.ui.save.SaveViewModel
|
||||
import app.omnivore.omnivore.ui.settings.PolicyWebView
|
||||
import app.omnivore.omnivore.ui.settings.SettingsView
|
||||
import app.omnivore.omnivore.ui.settings.SettingsViewModel
|
||||
import app.omnivore.omnivore.navigation.Routes
|
||||
import app.omnivore.omnivore.feature.auth.LoginViewModel
|
||||
import app.omnivore.omnivore.feature.auth.WelcomeScreen
|
||||
import app.omnivore.omnivore.feature.components.LabelsViewModel
|
||||
import app.omnivore.omnivore.feature.editinfo.EditInfoViewModel
|
||||
import app.omnivore.omnivore.feature.library.LibraryView
|
||||
import app.omnivore.omnivore.feature.library.LibraryViewModel
|
||||
import app.omnivore.omnivore.feature.library.SearchView
|
||||
import app.omnivore.omnivore.feature.library.SearchViewModel
|
||||
import app.omnivore.omnivore.feature.save.SaveViewModel
|
||||
import app.omnivore.omnivore.feature.settings.PolicyWebView
|
||||
import app.omnivore.omnivore.feature.settings.SettingsView
|
||||
import app.omnivore.omnivore.feature.settings.SettingsViewModel
|
||||
|
||||
@Composable
|
||||
fun RootView(
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.save
|
||||
package app.omnivore.omnivore.feature.save
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.foundation.background
|
||||
@ -16,7 +16,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.ui.reader.WebReaderLoadingContainerActivity
|
||||
import app.omnivore.omnivore.feature.reader.WebReaderLoadingContainerActivity
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.save
|
||||
package app.omnivore.omnivore.feature.save
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Intent
|
||||
@ -12,7 +12,6 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment.Companion.TopCenter
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.save
|
||||
package app.omnivore.omnivore.feature.save
|
||||
|
||||
import android.util.Patterns
|
||||
import androidx.compose.runtime.getValue
|
||||
@ -8,13 +8,13 @@ import androidx.compose.ui.text.intl.Locale
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.omnivore.omnivore.Constants
|
||||
import app.omnivore.omnivore.DatastoreKeys
|
||||
import app.omnivore.omnivore.DatastoreRepository
|
||||
import app.omnivore.omnivore.utils.Constants
|
||||
import app.omnivore.omnivore.utils.DatastoreKeys
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.graphql.generated.SaveUrlMutation
|
||||
import app.omnivore.omnivore.graphql.generated.type.SaveUrlInput
|
||||
import app.omnivore.omnivore.ui.ResourceProvider
|
||||
import app.omnivore.omnivore.feature.ResourceProvider
|
||||
import com.apollographql.apollo3.ApolloClient
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.savedItemViews
|
||||
package app.omnivore.omnivore.feature.savedItemViews
|
||||
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
@ -19,12 +19,12 @@ import androidx.compose.ui.text.toLowerCase
|
||||
import androidx.compose.ui.text.toUpperCase
|
||||
import androidx.compose.ui.unit.*
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.ui.components.LabelChip
|
||||
import app.omnivore.omnivore.ui.components.LabelChipColors
|
||||
import app.omnivore.omnivore.ui.library.SavedItemAction
|
||||
import app.omnivore.omnivore.ui.library.SavedItemViewModel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.feature.components.LabelChipColors
|
||||
import app.omnivore.omnivore.feature.components.LabelFilterChip
|
||||
import app.omnivore.omnivore.feature.library.SavedItemAction
|
||||
import app.omnivore.omnivore.feature.library.SavedItemViewModel
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class)
|
||||
@ -108,9 +108,10 @@ fun SavedItemCard(
|
||||
savedItem.labels.filter { !isFlairLabel(it) }.sortedWith(compareBy { it.name.toLowerCase(Locale.current) }).forEach { label ->
|
||||
val chipColors = LabelChipColors.fromHex(label.color)
|
||||
|
||||
LabelChip(
|
||||
name = label.name,
|
||||
colors = chipColors,
|
||||
LabelFilterChip(
|
||||
onClick = { },
|
||||
label = label.name,
|
||||
//colors = chipColors,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package app.omnivore.omnivore.feature.savedItemViews
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.feature.library.SavedItemAction
|
||||
import app.omnivore.omnivore.feature.reader.WebReaderViewModel
|
||||
|
||||
@Composable
|
||||
fun SavedItemContextMenu(
|
||||
isExpanded: Boolean,
|
||||
isArchived: Boolean,
|
||||
context: Context,
|
||||
webReaderViewModel: WebReaderViewModel,
|
||||
onDismiss: () -> Unit,
|
||||
actionHandler: (SavedItemAction) -> Unit
|
||||
) {
|
||||
val menuOptions = listOf(
|
||||
MenuItemOption(R.string.saved_item_context_menu_action_edit_info, SavedItemAction.EditInfo),
|
||||
MenuItemOption(
|
||||
R.string.saved_item_context_menu_action_edit_labels,
|
||||
SavedItemAction.EditLabels
|
||||
),
|
||||
MenuItemOption(
|
||||
textResourceId = if (isArchived) R.string.saved_item_context_menu_action_unarchive else R.string.saved_item_context_menu_action_archive,
|
||||
action = if (isArchived) SavedItemAction.Unarchive else SavedItemAction.Archive
|
||||
),
|
||||
MenuItemOption(
|
||||
textResourceId = R.string.saved_item_context_menu_action_share_original,
|
||||
customAction = {
|
||||
webReaderViewModel.showShareLinkSheet(context)
|
||||
onDismiss()
|
||||
}
|
||||
),
|
||||
MenuItemOption(R.string.saved_item_context_menu_action_remove_item, SavedItemAction.Delete)
|
||||
)
|
||||
|
||||
DropdownMenu(
|
||||
expanded = isExpanded,
|
||||
onDismissRequest = onDismiss
|
||||
) {
|
||||
menuOptions.forEach { option ->
|
||||
if (option.customAction != null) {
|
||||
DropdownMenuItem(
|
||||
text = { Text( text = stringResource(option.textResourceId), fontWeight = FontWeight.Normal) },
|
||||
onClick = {
|
||||
option.customAction.invoke()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DropdownMenuItem(
|
||||
text = { Text( text = stringResource(option.textResourceId), fontWeight = FontWeight.Normal) },
|
||||
onClick = {
|
||||
option.action?.let { actionHandler(it) }
|
||||
onDismiss()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MenuItemOption(
|
||||
val textResourceId: Int,
|
||||
val action: SavedItemAction? = null,
|
||||
val customAction: (() -> Unit)? = null
|
||||
)
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.savedItemViews
|
||||
package app.omnivore.omnivore.feature.savedItemViews
|
||||
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
@ -10,8 +10,8 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.*
|
||||
import app.omnivore.omnivore.persistence.entities.TypeaheadCardData
|
||||
import app.omnivore.omnivore.ui.library.SavedItemAction
|
||||
import app.omnivore.omnivore.core.database.entities.TypeaheadCardData
|
||||
import app.omnivore.omnivore.feature.library.SavedItemAction
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.settings
|
||||
package app.omnivore.omnivore.feature.settings
|
||||
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.settings
|
||||
package app.omnivore.omnivore.feature.settings
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.settings
|
||||
package app.omnivore.omnivore.feature.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.ViewGroup
|
||||
@ -14,7 +14,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.navigation.NavHostController
|
||||
import app.omnivore.omnivore.Routes
|
||||
import app.omnivore.omnivore.navigation.Routes
|
||||
import app.omnivore.omnivore.R
|
||||
|
||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "SetJavaScriptEnabled")
|
||||
@ -1,4 +1,4 @@
|
||||
package app.omnivore.omnivore.ui.settings
|
||||
package app.omnivore.omnivore.feature.settings
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@ -18,8 +18,8 @@ import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavHostController
|
||||
import app.omnivore.omnivore.BuildConfig
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.Routes
|
||||
import app.omnivore.omnivore.ui.auth.LoginViewModel
|
||||
import app.omnivore.omnivore.navigation.Routes
|
||||
import app.omnivore.omnivore.feature.auth.LoginViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user