mirror of
https://github.com/florisboard/florisboard.git
synced 2024-09-20 12:02:19 +02:00
Introduce new 'FlorisRef' class as replacement for 'AssetRef'
This commit is contained in:
parent
7f09d1a1d1
commit
f3aa739e72
@ -17,7 +17,7 @@ android {
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
freeCompilerArgs = listOf("-Xallow-result-return-type", "-Xopt-in=kotlin.RequiresOptIn")
|
||||
freeCompilerArgs = listOf("-Xallow-result-return-type", "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.contracts.ExperimentalContracts")
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
|
@ -14,15 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalContracts::class)
|
||||
|
||||
package dev.patrickgold.florisboard.debug
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
@ -14,13 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalContracts::class)
|
||||
|
||||
package dev.patrickgold.florisboard.ime.keyboard
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.DrawableRes
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalContracts::class)
|
||||
|
||||
package dev.patrickgold.florisboard.ime.spelling
|
||||
|
||||
import dev.patrickgold.florisboard.common.NativeInstanceWrapper
|
||||
@ -26,7 +24,6 @@ import dev.patrickgold.florisboard.ime.nlp.Word
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.*
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalContracts::class)
|
||||
|
||||
package dev.patrickgold.florisboard.ime.text.keyboard
|
||||
|
||||
import androidx.collection.SparseArrayCompat
|
||||
@ -24,7 +22,6 @@ import dev.patrickgold.florisboard.debug.*
|
||||
import dev.patrickgold.florisboard.ime.core.Subtype
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
@ -24,6 +24,7 @@ package dev.patrickgold.florisboard.res
|
||||
* @property path The relative path to the asset within [source]. Must not begin and end with a
|
||||
* forward slash.
|
||||
*/
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using the new type and phase out this class.")
|
||||
data class AssetRef(
|
||||
val source: AssetSource,
|
||||
val path: String
|
||||
@ -42,8 +43,20 @@ data class AssetRef(
|
||||
return Result.success(AssetRef(retSource, items[1]))
|
||||
}
|
||||
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using FlorisUri.assets(path)",
|
||||
ReplaceWith(
|
||||
"FlorisRef.assets(path)",
|
||||
"dev.patrickgold.florisboard.res.FlorisRef"
|
||||
)
|
||||
)
|
||||
fun assets(path: String) = AssetRef(AssetSource.Assets, path)
|
||||
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using FlorisUri.internal(path)",
|
||||
ReplaceWith(
|
||||
"FlorisRef.internal(path)",
|
||||
"dev.patrickgold.florisboard.res.FlorisRef"
|
||||
)
|
||||
)
|
||||
fun internal(path: String) = AssetRef(AssetSource.Internal, path)
|
||||
}
|
||||
|
||||
|
@ -20,17 +20,20 @@ package dev.patrickgold.florisboard.res
|
||||
* Sealed class which specifies where an asset comes from. There are 3 different types, all of which
|
||||
* require a different approach on how to access the actual asset.
|
||||
*/
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using the new type and phase out this class.")
|
||||
sealed class AssetSource {
|
||||
/**
|
||||
* The asset comes pre-built with the application, thus all paths must be relative to the asset
|
||||
* directory of FlorisBoard.
|
||||
*/
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using FlorisUri.assets(path)")
|
||||
object Assets : AssetSource()
|
||||
|
||||
/**
|
||||
* The asset is saved in the internal storage of FlorisBoard, all relative paths must therefore
|
||||
* be treated as such.
|
||||
*/
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using FlorisUri.internal(path)")
|
||||
object Internal : AssetSource()
|
||||
|
||||
/**
|
||||
@ -38,6 +41,7 @@ sealed class AssetSource {
|
||||
* data. Currently NYI.
|
||||
* TODO: Implement external extensions
|
||||
*/
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using the new type and phase out this class.")
|
||||
data class External(val packageName: String) : AssetSource() {
|
||||
override fun toString(): String {
|
||||
return super.toString()
|
||||
@ -47,6 +51,7 @@ sealed class AssetSource {
|
||||
companion object {
|
||||
private val externalRegex: Regex = """^external\\(([a-z]+\\.)*[a-z]+\\)\$""".toRegex()
|
||||
|
||||
@Deprecated("This class will slowly be replaced by '.res.FlorisRef', as it unifies the Android URI type with the internal referencing system. Consider using the new type and phase out this class.")
|
||||
fun fromString(str: String): Result<AssetSource> {
|
||||
return when (val string = str.lowercase()) {
|
||||
"assets" -> Result.success(Assets)
|
||||
|
@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalContracts::class)
|
||||
|
||||
package dev.patrickgold.florisboard.res
|
||||
|
||||
import android.content.Context
|
||||
@ -24,7 +22,6 @@ import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.BufferedReader
|
||||
import java.io.BufferedWriter
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
189
app/src/main/java/dev/patrickgold/florisboard/res/FlorisRef.kt
Normal file
189
app/src/main/java/dev/patrickgold/florisboard/res/FlorisRef.kt
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Patrick Goldinger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.res
|
||||
|
||||
import android.net.Uri
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* A universal resource reference, capable to point to destinations within
|
||||
* FlorisBoard's APK assets, cache and internal storage, external resources
|
||||
* provided to FlorisBoard via content URIs, as well as hyperlinks.
|
||||
* [android.net.Uri] is used as the underlying implementation for storing the
|
||||
* reference and also handles parsing of raw string URIs.
|
||||
*
|
||||
* The reference is immutable. If a change is required, consider constructing
|
||||
* a new reference with the provided builder methods.
|
||||
*
|
||||
* @property uri The underlying URI, which can be used for external references
|
||||
* to pass along to the system.
|
||||
*/
|
||||
@JvmInline
|
||||
value class FlorisRef private constructor(val uri: Uri) {
|
||||
companion object {
|
||||
private const val SCHEME_FLORIS_ASSETS = "floris-assets"
|
||||
private const val SCHEME_FLORIS_CACHE = "floris-cache"
|
||||
private const val SCHEME_FLORIS_INTERNAL = "floris-internal"
|
||||
|
||||
/**
|
||||
* Constructs a new [FlorisRef] pointing to a resource within the
|
||||
* FlorisBoard APK assets.
|
||||
*
|
||||
* @param path The relative path from the APK assets root the resource
|
||||
* is located.
|
||||
*
|
||||
* @return The newly constructed reference.
|
||||
*/
|
||||
fun assets(path: String) = Uri.Builder().run {
|
||||
scheme(SCHEME_FLORIS_ASSETS)
|
||||
path(path)
|
||||
FlorisRef(build())
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new [FlorisRef] pointing to a resource within the
|
||||
* cache storage of FlorisBoard.
|
||||
*
|
||||
* @param path The relative path from the cache root directory.
|
||||
*
|
||||
* @return The newly constructed reference.
|
||||
*/
|
||||
fun cache(path: String) = Uri.Builder().run {
|
||||
scheme(SCHEME_FLORIS_CACHE)
|
||||
path(path)
|
||||
FlorisRef(build())
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new [FlorisRef] pointing to a resource within the
|
||||
* internal storage of FlorisBoard.
|
||||
*
|
||||
* @param path The relative path from the internal storage root directory.
|
||||
*
|
||||
* @return The newly constructed reference.
|
||||
*/
|
||||
fun internal(path: String) = Uri.Builder().run {
|
||||
scheme(SCHEME_FLORIS_INTERNAL)
|
||||
path(path)
|
||||
FlorisRef(build())
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new reference from given [uri], this can point to any
|
||||
* destination, regardless of within FlorisBoard or not.
|
||||
*
|
||||
* @param uri The destination, denoted by a system URI format.
|
||||
*
|
||||
* @return The newly constructed reference.
|
||||
*/
|
||||
fun from(uri: Uri) = FlorisRef(uri)
|
||||
|
||||
/**
|
||||
* Constructs a new reference from given [str], this can point to any
|
||||
* destination, regardless of within FlorisBoard or not.
|
||||
*
|
||||
* @param str An RFC 2396-compliant, encoded URI string.
|
||||
*
|
||||
* @return The newly constructed reference.
|
||||
*/
|
||||
fun from(str: String) = FlorisRef(Uri.parse(str))
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the scheme indicates a reference to a FlorisBoard APK asset
|
||||
* resource, false otherwise.
|
||||
*/
|
||||
val isAssets: Boolean
|
||||
get() = uri.scheme == SCHEME_FLORIS_ASSETS
|
||||
|
||||
/**
|
||||
* True if the scheme indicates a reference to a FlorisBoard cache
|
||||
* resource, false otherwise.
|
||||
*/
|
||||
val isCache: Boolean
|
||||
get() = uri.scheme == SCHEME_FLORIS_CACHE
|
||||
|
||||
/**
|
||||
* True if the scheme indicates a reference to a FlorisBoard internal
|
||||
* storage resource, false otherwise.
|
||||
*/
|
||||
val isInternal: Boolean
|
||||
get() = uri.scheme == SCHEME_FLORIS_INTERNAL
|
||||
|
||||
/**
|
||||
* True if the scheme references any other external resource (URL, content
|
||||
* resolver, etc.), false otherwise.
|
||||
*/
|
||||
val isExternal: Boolean
|
||||
get() = !isAssets && !isCache && !isInternal
|
||||
|
||||
/**
|
||||
* Returns the scheme of this URI, or an empty string if no scheme is
|
||||
* specified.
|
||||
*/
|
||||
val scheme: String
|
||||
get() = uri.scheme ?: ""
|
||||
|
||||
/**
|
||||
* Returns the path of this URI, either relative or absolute depending on
|
||||
* the use case of this reference, or an empty string if no path is
|
||||
* specified.
|
||||
*/
|
||||
val path: String
|
||||
get() = uri.path ?: ""
|
||||
|
||||
/**
|
||||
* Allows this URI to be used depending on where this reference points to.
|
||||
* It is guaranteed that one of the four lambda parameters is executed.
|
||||
*
|
||||
* @param assets The lambda to run when the reference points to the FlorisBoard
|
||||
* APK assets. Defaults to do nothing.
|
||||
* @param cache The lambda to run when the reference points to the FlorisBoard
|
||||
* cache resources. Defaults to do nothing.
|
||||
* @param internal The lambda to run when the reference points to the FlorisBoard
|
||||
* internal storage. Defaults to do nothing.
|
||||
* @param external The lambda to run when the reference points to an external
|
||||
* resource. Defaults to do nothing.
|
||||
*/
|
||||
fun whenSchemeIs(
|
||||
assets: (ref: FlorisRef) -> Unit = { /* Do nothing */ },
|
||||
cache: (ref: FlorisRef) -> Unit = { /* Do nothing */ },
|
||||
internal: (ref: FlorisRef) -> Unit = { /* Do nothing */ },
|
||||
external: (ref: FlorisRef) -> Unit = { /* Do nothing */ }
|
||||
) {
|
||||
contract {
|
||||
callsInPlace(assets, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(cache, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(internal, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(external, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
when {
|
||||
isAssets -> assets(this)
|
||||
isCache -> internal(this)
|
||||
isInternal -> internal(this)
|
||||
else -> external(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoded string representation of this URI.
|
||||
*/
|
||||
override fun toString(): String {
|
||||
return uri.toString()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user