targetSdkVersion 31
This commit is contained in:
parent
d017a47363
commit
9c68857e6e
|
@ -3,6 +3,11 @@
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="1.8">
|
<bytecodeTargetLevel target="1.8">
|
||||||
<module name="apng" target="1.7" />
|
<module name="apng" target="1.7" />
|
||||||
|
<module name="SubwayTooter.apng_android" target="11" />
|
||||||
|
<module name="SubwayTooter.app" target="11" />
|
||||||
|
<module name="SubwayTooter.colorpicker" target="11" />
|
||||||
|
<module name="SubwayTooter.emoji" target="11" />
|
||||||
|
<module name="SubwayTooter.sample_apng" target="11" />
|
||||||
</bytecodeTargetLevel>
|
</bytecodeTargetLevel>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -4,10 +4,10 @@
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="delegatedBuild" value="false" />
|
|
||||||
<option name="testRunner" value="GRADLE" />
|
<option name="testRunner" value="GRADLE" />
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="gradleJvm" value="Embedded JDK" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="AndroidLintButtonStyle" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintButtonStyle" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="AndroidLintPluralsCandidate" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="AndroidLintSetTextI18n" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="AndroidLintSetTextI18n" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="BlockingMethodInNonBlockingContext" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="BlockingMethodInNonBlockingContext" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="ClassName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="ClassName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="ConstantConditionIf" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="ConstantConditionIf" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="ConvertTwoComparisonsToRangeCheck" enabled="false" level="INFO" enabled_by_default="false" />
|
<inspection_tool class="ConvertTwoComparisonsToRangeCheck" enabled="false" level="INFO" enabled_by_default="false" />
|
||||||
|
@ -23,14 +25,27 @@
|
||||||
<option name="m_maxLength" value="32" />
|
<option name="m_maxLength" value="32" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="JoinDeclarationAndAssignment" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="JoinDeclarationAndAssignment" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JsonStandardCompliance" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
<inspection_tool class="LocalVariableName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="LocalVariableName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="LoopToCallChain" enabled="false" level="INFO" enabled_by_default="false" />
|
<inspection_tool class="LoopToCallChain" enabled="false" level="INFO" enabled_by_default="false" />
|
||||||
<inspection_tool class="NumericOverflow" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="NumericOverflow" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="ObjectPropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="ObjectPropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="PrivatePropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="PrivatePropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="PropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
<inspection_tool class="PropertyName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
<inspection_tool class="TryFinallyCanBeTryWithResources" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="TryFinallyCanBeTryWithResources" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="UnnecessaryModuleDependencyInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="UnnecessaryModuleDependencyInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="UnusedProperty" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="UnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="UseWithIndex" enabled="false" level="INFO" enabled_by_default="false" />
|
<inspection_tool class="UseWithIndex" enabled="false" level="INFO" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="XmlDefaultAttributeValue" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="XmlDuplicatedId" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="XmlHighlighting" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="XmlUnusedNamespaceDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="YAMLDuplicatedKeys" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
|
@ -11,17 +11,17 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(include: ['*.jar'], dir: 'src/lib')
|
implementation fileTree(include: ['*.jar'], dir: 'src/lib')
|
||||||
implementation "com.google.guava:guava:28.1-jre"
|
implementation "com.google.guava:guava:28.1-jre"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib"
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
|
||||||
|
|
||||||
def ktor_version="1.5.0"
|
def ktorVersion="1.5.0"
|
||||||
implementation "io.ktor:ktor-client-core:$ktor_version"
|
implementation "io.ktor:ktor-client-core:$ktorVersion"
|
||||||
implementation "io.ktor:ktor-client-cio:$ktor_version"
|
implementation "io.ktor:ktor-client-cio:$ktorVersion"
|
||||||
implementation "io.ktor:ktor-client-features:$ktor_version"
|
implementation "io.ktor:ktor-client-features:$ktorVersion"
|
||||||
implementation "io.ktor:ktor-client-encoding:$ktor_version"
|
implementation "io.ktor:ktor-client-encoding:$ktorVersion"
|
||||||
|
|
||||||
// StringEscapeUtils.unescapeHtml4
|
// StringEscapeUtils.unescapeHtml4
|
||||||
implementation "org.apache.commons:commons-text:1.9"
|
implementation "org.apache.commons:commons-text:1.9"
|
||||||
|
@ -33,3 +33,7 @@ dependencies {
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
|
@ -30,11 +30,22 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
useIR = true
|
||||||
freeCompilerArgs += [
|
freeCompilerArgs += [
|
||||||
"-Xopt-in=kotlin.ExperimentalStdlibApi",
|
"-Xopt-in=kotlin.ExperimentalStdlibApi",
|
||||||
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
|
"-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi",
|
||||||
|
"-Xopt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||||
|
"-Xopt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
buildFeatures {
|
||||||
|
compose true
|
||||||
|
}
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion compose_version
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
|
@ -57,13 +68,6 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dexOptions {
|
|
||||||
jumboMode = true
|
|
||||||
preDexLibraries true
|
|
||||||
maxProcessCount 10
|
|
||||||
javaMaxHeapSize "3g"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate Signed APK のファイル名を変更
|
// Generate Signed APK のファイル名を変更
|
||||||
android.applicationVariants.all { variant ->
|
android.applicationVariants.all { variant ->
|
||||||
if (variant.buildType.name == "release") {
|
if (variant.buildType.name == "release") {
|
||||||
|
@ -73,7 +77,8 @@ android {
|
||||||
def versionName = defaultConfig.versionName
|
def versionName = defaultConfig.versionName
|
||||||
def flavor = variant.flavorName
|
def flavor = variant.flavorName
|
||||||
def date = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
|
def date = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
|
||||||
outputFileName = "../../SubwayTooter-${flavor}-${versionCode}-${versionName}-${date}.apk"
|
def branch = gitBranch()
|
||||||
|
outputFileName = "../../SubwayTooter-${branch}-${flavor}-${versionCode}-${versionName}-${date}.apk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,12 +86,27 @@ android {
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
// https://github.com/Kotlin/kotlinx.coroutines/issues/1064
|
// https://github.com/Kotlin/kotlinx.coroutines/issues/1064
|
||||||
pickFirst("META-INF/atomicfu.kotlin_module")
|
pickFirst("META-INF/atomicfu.kotlin_module")
|
||||||
|
resources {
|
||||||
|
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useLibrary 'android.test.base'
|
useLibrary 'android.test.base'
|
||||||
useLibrary 'android.test.mock'
|
useLibrary 'android.test.mock'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static def gitBranch() {
|
||||||
|
def branch = "(no branch)"
|
||||||
|
def proc = "git status".execute()
|
||||||
|
proc.in.eachLine { line ->
|
||||||
|
def matcher = line =~ /\AOn branch (\S+)/
|
||||||
|
if (matcher) branch = matcher.group(1)
|
||||||
|
}
|
||||||
|
proc.err.eachLine { line -> println line }
|
||||||
|
proc.waitFor()
|
||||||
|
branch
|
||||||
|
}
|
||||||
|
|
||||||
kapt {
|
kapt {
|
||||||
useBuildCache = true
|
useBuildCache = true
|
||||||
}
|
}
|
||||||
|
@ -109,20 +129,17 @@ dependencies {
|
||||||
|
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||||
//noinspection KtxExtensionAvailable
|
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
|
|
||||||
|
|
||||||
|
|
||||||
// DrawerLayout
|
// DrawerLayout
|
||||||
implementation "androidx.drawerlayout:drawerlayout:1.1.1"
|
implementation "androidx.drawerlayout:drawerlayout:1.1.1"
|
||||||
|
|
||||||
// NavigationView
|
// NavigationView
|
||||||
implementation "com.google.android.material:material:1.3.0"
|
implementation "com.google.android.material:material:1.4.0"
|
||||||
|
|
||||||
// PreferenceManager
|
// PreferenceManager
|
||||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||||
|
|
||||||
implementation "androidx.exifinterface:exifinterface:1.3.2"
|
implementation "androidx.exifinterface:exifinterface:1.3.3"
|
||||||
|
|
||||||
// CustomTabs
|
// CustomTabs
|
||||||
implementation "androidx.browser:browser:1.3.0"
|
implementation "androidx.browser:browser:1.3.0"
|
||||||
|
@ -155,19 +172,17 @@ dependencies {
|
||||||
|
|
||||||
testImplementation "junit:junit:$junit_version" // しばらくはkotlin-testとjunitを併用
|
testImplementation "junit:junit:$junit_version" // しばらくはkotlin-testとjunitを併用
|
||||||
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.8.1'
|
def okhttpVersion = "4.9.2"
|
||||||
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.8.1'
|
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||||
testImplementation 'com.squareup.okhttp3:mockwebserver:3.12.1'
|
implementation "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion"
|
||||||
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.12.1'
|
testImplementation "com.squareup.okhttp3:mockwebserver:$okhttpVersion"
|
||||||
|
androidTestImplementation "'com.squareup.okhttp3:mockwebserver:$okhttpVersion"
|
||||||
|
|
||||||
def glideVersion = '4.11.0'
|
def glideVersion = '4.12.0'
|
||||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||||
implementation "com.github.bumptech.glide:annotations:$glideVersion"
|
implementation "com.github.bumptech.glide:annotations:$glideVersion"
|
||||||
implementation("com.github.bumptech.glide:okhttp3-integration:$glideVersion") {
|
implementation("com.github.bumptech.glide:okhttp3-integration:$glideVersion") {
|
||||||
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
|
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
|
||||||
// 推移的な依存関係の除外
|
|
||||||
// glide 4.9.0 は okhttp3 3.9.1を使ってる
|
|
||||||
// http://bumptech.github.io/glide/int/about.html#how-do-i-use-a-specific-version-of-okhttp-volley-or-other-third-party-library
|
|
||||||
}
|
}
|
||||||
kapt "com.github.bumptech.glide:compiler:$glideVersion"
|
kapt "com.github.bumptech.glide:compiler:$glideVersion"
|
||||||
|
|
||||||
|
@ -190,7 +205,7 @@ dependencies {
|
||||||
|
|
||||||
implementation 'com.astuetz:pagerslidingtabstrip:1.0.1'
|
implementation 'com.astuetz:pagerslidingtabstrip:1.0.1'
|
||||||
|
|
||||||
implementation 'com.google.android.exoplayer:exoplayer:2.15.0'
|
implementation 'com.google.android.exoplayer:exoplayer:2.15.1'
|
||||||
/*
|
/*
|
||||||
WARNING: [Processor] Library '…\exoplayer-ui-2.12.0.aar' contains references to both AndroidX and old support library. This seems like the library is partially migrated. Jetifier will try to rewrite the library anyway.
|
WARNING: [Processor] Library '…\exoplayer-ui-2.12.0.aar' contains references to both AndroidX and old support library. This seems like the library is partially migrated. Jetifier will try to rewrite the library anyway.
|
||||||
Example of androidX reference: 'androidx/core/app/NotificationCompat$Builder'
|
Example of androidX reference: 'androidx/core/app/NotificationCompat$Builder'
|
||||||
|
@ -199,6 +214,46 @@ dependencies {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
implementation 'com.caverock:androidsvg-aar:1.4'
|
implementation 'com.caverock:androidsvg-aar:1.4'
|
||||||
|
|
||||||
|
|
||||||
|
// ViewModel
|
||||||
|
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
|
||||||
|
// LiveData
|
||||||
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
|
||||||
|
// Lifecycles only (without ViewModel or LiveData)
|
||||||
|
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
|
||||||
|
|
||||||
|
// Saved state module for ViewModel
|
||||||
|
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
|
||||||
|
|
||||||
|
// if using Java8, use the following instead of lifecycle-compiler
|
||||||
|
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
||||||
|
|
||||||
|
// optional - helpers for implementing LifecycleOwner in a Service
|
||||||
|
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
|
||||||
|
|
||||||
|
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
|
||||||
|
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
|
||||||
|
|
||||||
|
// optional - ReactiveStreams support for LiveData
|
||||||
|
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version"
|
||||||
|
|
||||||
|
// optional - Test helpers for LiveData
|
||||||
|
testImplementation "androidx.arch.core:core-testing:$arch_version"
|
||||||
|
|
||||||
|
implementation "com.google.accompanist:accompanist-flowlayout:0.20.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.runtime:runtime-livedata:$compose_version"
|
||||||
|
implementation "androidx.compose.material:material-icons-extended:$compose_version"
|
||||||
|
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
|
||||||
|
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
|
||||||
|
|
||||||
|
implementation 'androidx.activity:activity-compose:1.4.0-rc01'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
|
@ -33,6 +33,7 @@ class TestMisskeyMentionAndroid {
|
||||||
// val a="""[[ ]""".toRegex()
|
// val a="""[[ ]""".toRegex()
|
||||||
|
|
||||||
// IDEで警告が出るが、Androidは正規表現エンジンが異なるので仕方ない
|
// IDEで警告が出るが、Androidは正規表現エンジンが異なるので仕方ない
|
||||||
|
@Suppress("RegExpRedundantNestedCharacterClass")
|
||||||
assertEquals(true, """[[ ]]][ ]""".toRegex().matches(" ] "))
|
assertEquals(true, """[[ ]]][ ]""".toRegex().matches(" ] "))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package jp.juggler.subwaytooter
|
package jp.juggler.subwaytooter
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.runner.AndroidJUnit4
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import jp.juggler.subwaytooter.api.TootApiCallback
|
import jp.juggler.subwaytooter.api.TootApiCallback
|
||||||
import jp.juggler.subwaytooter.api.TootApiClient
|
import jp.juggler.subwaytooter.api.TootApiClient
|
||||||
import jp.juggler.subwaytooter.api.entity.Host
|
import jp.juggler.subwaytooter.api.entity.Host
|
||||||
|
@ -10,13 +10,13 @@ import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
import jp.juggler.subwaytooter.util.SimpleHttpClientImpl
|
import jp.juggler.subwaytooter.util.SimpleHttpClientImpl
|
||||||
import jp.juggler.util.LogCategory
|
import jp.juggler.util.LogCategory
|
||||||
import jp.juggler.util.MySslSocketFactory
|
import jp.juggler.util.MySslSocketFactory
|
||||||
import junit.framework.Assert.assertNotNull
|
|
||||||
import junit.framework.Assert.assertNull
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.ConnectionSpec
|
import okhttp3.ConnectionSpec
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.junit.Assert.assertNotNull
|
||||||
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -38,10 +38,14 @@ class TestTootInstance {
|
||||||
.readTimeout(60.toLong(), TimeUnit.SECONDS)
|
.readTimeout(60.toLong(), TimeUnit.SECONDS)
|
||||||
.writeTimeout(60.toLong(), TimeUnit.SECONDS)
|
.writeTimeout(60.toLong(), TimeUnit.SECONDS)
|
||||||
.pingInterval(10, TimeUnit.SECONDS)
|
.pingInterval(10, TimeUnit.SECONDS)
|
||||||
.connectionSpecs(Collections.singletonList(ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
.connectionSpecs(
|
||||||
|
Collections.singletonList(
|
||||||
|
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||||
.allEnabledCipherSuites()
|
.allEnabledCipherSuites()
|
||||||
.allEnabledTlsVersions()
|
.allEnabledTlsVersions()
|
||||||
.build()))
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
.sslSocketFactory(MySslSocketFactory, MySslSocketFactory.trustManager)
|
.sslSocketFactory(MySslSocketFactory, MySslSocketFactory.trustManager)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ class TestTootInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val appContext = InstrumentationRegistry.getTargetContext()!!
|
private val appContext = InstrumentationRegistry.getInstrumentation().targetContext!!
|
||||||
|
|
||||||
val client = TootApiClient(
|
val client = TootApiClient(
|
||||||
context = appContext,
|
context = appContext,
|
||||||
|
@ -75,10 +79,10 @@ class TestTootInstance {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
suspend fun a(host: Host) {
|
suspend fun a(host: Host) {
|
||||||
val (ti,ri) = TootInstance.get(client,host )
|
val (ti, ri) = TootInstance.getEx(client, hostArg = host)
|
||||||
assertNotNull(ti)
|
assertNotNull(ti)
|
||||||
assertNull(ri?.error)
|
assertNull(ri?.error)
|
||||||
ti!!.run{ log.d("${instanceType} ${uri} ${version}")}
|
ti!!.run { log.d("$instanceType $uri $version") }
|
||||||
|
|
||||||
}
|
}
|
||||||
a(Host.parse("mastodon.juggler.jp"))
|
a(Host.parse("mastodon.juggler.jp"))
|
||||||
|
@ -92,10 +96,10 @@ class TestTootInstance {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
suspend fun a(account: SavedAccount) {
|
suspend fun a(account: SavedAccount) {
|
||||||
val (ti,ri) = TootInstance.get(client,account = account )
|
val (ti, ri) = TootInstance.getEx(client, account = account)
|
||||||
assertNull(ri?.error)
|
assertNull(ri?.error)
|
||||||
assertNotNull(ti)
|
assertNotNull(ti)
|
||||||
ti!!.run{ log.d("${account.acct} ${instanceType} ${uri} ${version}")}
|
ti!!.run { log.d("${account.acct} $instanceType $uri $version") }
|
||||||
}
|
}
|
||||||
a(SavedAccount(45, "tateisu@mastodon.juggler.jp"))
|
a(SavedAccount(45, "tateisu@mastodon.juggler.jp"))
|
||||||
a(SavedAccount(45, "tateisu@misskey.io", misskeyVersion = 12))
|
a(SavedAccount(45, "tateisu@misskey.io", misskeyVersion = 12))
|
||||||
|
|
|
@ -3,19 +3,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="jp.juggler.subwaytooter">
|
package="jp.juggler.subwaytooter">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
|
||||||
tools:ignore="ScopedStorage" />
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
||||||
<!-- CAMERAパーミッションをつけるとPlayストアにプライバシーポリシーを記載する必要がある -->
|
|
||||||
<!--<uses-permission android:name="android.permission.CAMERA"/>-->
|
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
|
|
||||||
<!-- (自アプリ以外で)指定URLを開けるアプリの存在確認 -->
|
<!-- (自アプリ以外で)指定URLを開けるアプリの存在確認 -->
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
@ -62,6 +50,20 @@
|
||||||
<!-- </intent>-->
|
<!-- </intent>-->
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
tools:ignore="ScopedStorage" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<!-- CAMERAパーミッションをつけるとPlayストアにプライバシーポリシーを記載する必要がある -->
|
||||||
|
<!--<uses-permission android:name="android.permission.CAMERA"/>-->
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App1"
|
android:name=".App1"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -75,30 +77,11 @@
|
||||||
android:theme="@style/AppTheme.Light"
|
android:theme="@style/AppTheme.Light"
|
||||||
tools:ignore="UnusedAttribute">
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<receiver android:name=".EventReceiver">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".notification.PollingService"
|
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
|
||||||
|
|
||||||
<service android:name=".notification.PollingForegrounder" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActMain"
|
android:name=".ActMain"
|
||||||
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
|
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
@ -108,9 +91,8 @@
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActCallback"
|
android:name=".ActCallback"
|
||||||
android:label="@string/app_name"
|
android:exported="true"
|
||||||
|
android:label="@string/app_name">
|
||||||
>
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
@ -195,105 +177,122 @@
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActPost"
|
android:name=".ActPost"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/act_post"
|
android:label="@string/act_post"
|
||||||
|
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
|
||||||
<!--suppress AndroidElementNotAllowed -->
|
<!--suppress AndroidElementNotAllowed -->
|
||||||
<layout
|
<layout
|
||||||
android:defaultWidth="320dp"
|
|
||||||
android:defaultHeight="480dp"
|
android:defaultHeight="480dp"
|
||||||
|
android:defaultWidth="320dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minWidth="64dp"
|
|
||||||
android:minHeight="64dp"
|
android:minHeight="64dp"
|
||||||
|
android:minWidth="64dp"
|
||||||
tools:ignore="UnusedAttribute" />
|
tools:ignore="UnusedAttribute" />
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActAccountSetting"
|
android:name=".ActAccountSetting"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/account_setting"
|
android:label="@string/account_setting"
|
||||||
|
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActAppSetting"
|
android:name=".ActAppSetting"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/app_setting"
|
android:label="@string/app_setting"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActColumnList"
|
android:name=".ActColumnList"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/column_list"
|
android:label="@string/column_list"
|
||||||
|
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActAbout"
|
android:name=".ActAbout"
|
||||||
android:label="@string/app_about"
|
android:exported="false"
|
||||||
|
android:label="@string/app_about" />
|
||||||
|
|
||||||
/>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActOSSLicense"
|
android:name=".ActOSSLicense"
|
||||||
android:label="@string/oss_license"
|
android:exported="false"
|
||||||
|
android:label="@string/oss_license" />
|
||||||
|
|
||||||
/>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActMutedApp"
|
android:name=".ActMutedApp"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/muted_app" />
|
android:label="@string/muted_app" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActMutedPseudoAccount"
|
android:name=".ActMutedPseudoAccount"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/muted_users_from_pseudo_account" />
|
android:label="@string/muted_users_from_pseudo_account" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActMutedWord"
|
android:name=".ActMutedWord"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/muted_word" />
|
android:label="@string/muted_word" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActFavMute"
|
android:name=".ActFavMute"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/fav_muted_user_long" />
|
android:label="@string/fav_muted_user_long" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActKeywordFilter"
|
android:name=".ActKeywordFilter"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/keyword_filter_new"
|
android:label="@string/keyword_filter_new"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActHighlightWordList"
|
android:name=".ActHighlightWordList"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/highlight_word" />
|
android:label="@string/highlight_word" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActHighlightWordEdit"
|
android:name=".ActHighlightWordEdit"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/highlight_word" />
|
android:label="@string/highlight_word" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActColumnCustomize"
|
android:name=".ActColumnCustomize"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/color_and_background"
|
android:label="@string/color_and_background"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActLanguageFilter"
|
android:name=".ActLanguageFilter"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/language_filter"
|
android:label="@string/language_filter"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActDrawableList"
|
android:name=".ActDrawableList"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/drawable_list"
|
android:label="@string/drawable_list"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActNickname"
|
android:name=".ActNickname"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/nickname_and_color_and_notification_sound"
|
android:label="@string/nickname_and_color_and_notification_sound"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActText"
|
android:name=".ActText"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/select_and_copy"
|
android:label="@string/select_and_copy"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActMediaViewer"
|
android:name=".ActMediaViewer"
|
||||||
|
android:exported="false"
|
||||||
android:theme="@style/AppTheme.Dark.NoActionBar" />
|
android:theme="@style/AppTheme.Dark.NoActionBar" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActExitReasons"
|
android:name=".ActExitReasons"
|
||||||
|
android:exported="false"
|
||||||
android:label="@string/exit_reasons"
|
android:label="@string/exit_reasons"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
|
||||||
|
|
||||||
|
@ -301,6 +300,18 @@
|
||||||
android:name="android.max_aspect"
|
android:name="android.max_aspect"
|
||||||
android:value="100.0" />
|
android:value="100.0" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||||
|
android:resource="@drawable/ic_notification" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.firebase.messaging.default_notification_color"
|
||||||
|
android:resource="@color/Light_colorAccent" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.allow_multiple_resumed_activities"
|
||||||
|
android:value="true" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="jp.juggler.subwaytooter.FileProvider"
|
android:authorities="jp.juggler.subwaytooter.FileProvider"
|
||||||
|
@ -311,38 +322,50 @@
|
||||||
android:resource="@xml/file_provider_path" />
|
android:resource="@xml/file_provider_path" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<receiver android:name=".DownloadReceiver">
|
<receiver
|
||||||
|
android:name=".EventReceiver"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".DownloadReceiver"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
|
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
|
||||||
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
|
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
|
||||||
|
See README(https://goo.gl/l4GJaQ) for more. -->
|
||||||
|
<service
|
||||||
|
android:name=".notification.PollingService"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
|
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
|
||||||
|
notification message. See README(https://goo.gl/6BKBk7) for more. -->
|
||||||
|
<service android:name=".notification.PollingForegrounder" />
|
||||||
|
|
||||||
|
<!--https://android-developers.googleblog.com/2018/11/get-your-app-ready-for-foldable-phones.html-->
|
||||||
<service
|
<service
|
||||||
android:name=".MyFirebaseMessagingService"
|
android:name=".MyFirebaseMessagingService"
|
||||||
|
android:exported="true"
|
||||||
tools:ignore="ExportedService">
|
tools:ignore="ExportedService">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
|
|
||||||
See README(https://goo.gl/l4GJaQ) for more. -->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
|
||||||
android:resource="@drawable/ic_notification" />
|
|
||||||
|
|
||||||
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
|
|
||||||
notification message. See README(https://goo.gl/6BKBk7) for more. -->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.firebase.messaging.default_notification_color"
|
|
||||||
android:resource="@color/Light_colorAccent" />
|
|
||||||
|
|
||||||
<!--https://android-developers.googleblog.com/2018/11/get-your-app-ready-for-foldable-phones.html-->
|
|
||||||
<meta-data
|
|
||||||
android:name="android.allow_multiple_resumed_activities"
|
|
||||||
android:value="true" />
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -42,8 +42,6 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
|
||||||
internal const val COLOR_DIALOG_ID_ACCT_TEXT = 4
|
internal const val COLOR_DIALOG_ID_ACCT_TEXT = 4
|
||||||
internal const val COLOR_DIALOG_ID_CONTENT_TEXT = 5
|
internal const val COLOR_DIALOG_ID_CONTENT_TEXT = 5
|
||||||
|
|
||||||
internal const val REQUEST_CODE_PICK_BACKGROUND = 1
|
|
||||||
|
|
||||||
internal const val PROGRESS_MAX = 65536
|
internal const val PROGRESS_MAX = 65536
|
||||||
|
|
||||||
fun createIntent(activity: ActMain, idx: Int) =
|
fun createIntent(activity: ActMain, idx: Int) =
|
||||||
|
@ -72,7 +70,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
|
||||||
private var lastImageUri: String? = null
|
private var lastImageUri: String? = null
|
||||||
private var lastImageBitmap: Bitmap? = null
|
private var lastImageBitmap: Bitmap? = null
|
||||||
|
|
||||||
val arColumnBackgroundImage = activityResultHandler { ar ->
|
private val arColumnBackgroundImage = activityResultHandler { ar ->
|
||||||
val data = ar?.data
|
val data = ar?.data
|
||||||
if (data != null && ar.resultCode == RESULT_OK) {
|
if (data != null && ar.resultCode == RESULT_OK) {
|
||||||
data.handleGetContentResult(contentResolver)
|
data.handleGetContentResult(contentResolver)
|
||||||
|
|
|
@ -14,8 +14,6 @@ import android.view.*
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.inputmethod.InputConnectionCompat
|
|
||||||
import androidx.core.view.inputmethod.InputContentInfoCompat
|
|
||||||
import jp.juggler.subwaytooter.action.saveWindowSize
|
import jp.juggler.subwaytooter.action.saveWindowSize
|
||||||
import jp.juggler.subwaytooter.actpost.*
|
import jp.juggler.subwaytooter.actpost.*
|
||||||
import jp.juggler.subwaytooter.api.*
|
import jp.juggler.subwaytooter.api.*
|
||||||
|
@ -56,11 +54,6 @@ class ActPost : AppCompatActivity(),
|
||||||
const val KEY_QUOTE = "quote"
|
const val KEY_QUOTE = "quote"
|
||||||
const val KEY_SCHEDULED_STATUS = "scheduled_status"
|
const val KEY_SCHEDULED_STATUS = "scheduled_status"
|
||||||
|
|
||||||
const val KEY_ATTACHMENT_LIST = "attachment_list"
|
|
||||||
const val KEY_IN_REPLY_TO_ID = "in_reply_to_id"
|
|
||||||
const val KEY_IN_REPLY_TO_TEXT = "in_reply_to_text"
|
|
||||||
const val KEY_IN_REPLY_TO_IMAGE = "in_reply_to_image"
|
|
||||||
|
|
||||||
const val STATE_ALL = "all"
|
const val STATE_ALL = "all"
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
|
@ -97,8 +90,8 @@ class ActPost : AppCompatActivity(),
|
||||||
|
|
||||||
lateinit var btnAccount: Button
|
lateinit var btnAccount: Button
|
||||||
lateinit var btnVisibility: ImageButton
|
lateinit var btnVisibility: ImageButton
|
||||||
lateinit var btnAttachment: ImageButton
|
private lateinit var btnAttachment: ImageButton
|
||||||
lateinit var btnPost: ImageButton
|
private lateinit var btnPost: ImageButton
|
||||||
lateinit var llAttachment: View
|
lateinit var llAttachment: View
|
||||||
lateinit var ivMedia: List<MyNetworkImageView>
|
lateinit var ivMedia: List<MyNetworkImageView>
|
||||||
lateinit var cbNSFW: CheckBox
|
lateinit var cbNSFW: CheckBox
|
||||||
|
@ -121,7 +114,7 @@ class ActPost : AppCompatActivity(),
|
||||||
|
|
||||||
lateinit var tvCharCount: TextView
|
lateinit var tvCharCount: TextView
|
||||||
lateinit var handler: Handler
|
lateinit var handler: Handler
|
||||||
lateinit var formRoot: ActPostRootLinearLayout
|
private lateinit var formRoot: ActPostRootLinearLayout
|
||||||
|
|
||||||
lateinit var llReply: View
|
lateinit var llReply: View
|
||||||
lateinit var tvReplyTo: TextView
|
lateinit var tvReplyTo: TextView
|
||||||
|
@ -129,8 +122,8 @@ class ActPost : AppCompatActivity(),
|
||||||
lateinit var scrollView: ScrollView
|
lateinit var scrollView: ScrollView
|
||||||
|
|
||||||
lateinit var tvSchedule: TextView
|
lateinit var tvSchedule: TextView
|
||||||
lateinit var ibSchedule: ImageButton
|
private lateinit var ibSchedule: ImageButton
|
||||||
lateinit var ibScheduleReset: ImageButton
|
private lateinit var ibScheduleReset: ImageButton
|
||||||
|
|
||||||
lateinit var pref: SharedPreferences
|
lateinit var pref: SharedPreferences
|
||||||
lateinit var appState: AppState
|
lateinit var appState: AppState
|
||||||
|
@ -184,41 +177,6 @@ class ActPost : AppCompatActivity(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val commitContentListener =
|
|
||||||
InputConnectionCompat.OnCommitContentListener {
|
|
||||||
inputContentInfo: InputContentInfoCompat,
|
|
||||||
flags: Int,
|
|
||||||
_: Bundle?,
|
|
||||||
->
|
|
||||||
// Intercepts InputConnection#commitContent API calls.
|
|
||||||
// - inputContentInfo : content to be committed
|
|
||||||
// - flags : {@code 0} or {@link #INPUT_CONTENT_GRANT_READ_URI_PERMISSION}
|
|
||||||
// - opts : optional bundle data. This can be {@code null}
|
|
||||||
// return
|
|
||||||
// - true if this request is accepted by the application,
|
|
||||||
// no matter if the request is already handled or still being handled in background.
|
|
||||||
// - false to use the default implementation
|
|
||||||
|
|
||||||
// read and display inputContentInfo asynchronously
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 25 &&
|
|
||||||
flags and InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION != 0
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
inputContentInfo.requestPermission()
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
// return false if failed
|
|
||||||
return@OnCommitContentListener false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addAttachment(inputContentInfo.contentUri) {
|
|
||||||
inputContentInfo.releasePermission()
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -331,7 +289,11 @@ class ActPost : AppCompatActivity(),
|
||||||
openBrowser(span.linkInfo.url)
|
openBrowser(span.linkInfo.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(
|
||||||
|
requestCode: Int,
|
||||||
|
permissions: Array<String>,
|
||||||
|
grantResults: IntArray
|
||||||
|
) {
|
||||||
attachmentPicker.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
attachmentPicker.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
}
|
}
|
||||||
|
@ -407,7 +369,12 @@ class ActPost : AppCompatActivity(),
|
||||||
updateTextCount()
|
updateTextCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
override fun onItemSelected(
|
||||||
|
parent: AdapterView<*>?,
|
||||||
|
view: View?,
|
||||||
|
position: Int,
|
||||||
|
id: Long
|
||||||
|
) {
|
||||||
showPoll()
|
showPoll()
|
||||||
updateTextCount()
|
updateTextCount()
|
||||||
}
|
}
|
||||||
|
@ -463,7 +430,11 @@ class ActPost : AppCompatActivity(),
|
||||||
cbContentWarning.setOnCheckedChangeListener { _, _ -> showContentWarningEnabled() }
|
cbContentWarning.setOnCheckedChangeListener { _, _ -> showContentWarningEnabled() }
|
||||||
|
|
||||||
completionHelper = CompletionHelper(this, pref, appState.handler)
|
completionHelper = CompletionHelper(this, pref, appState.handler)
|
||||||
completionHelper.attachEditText(formRoot, etContent, false, object : CompletionHelper.Callback2 {
|
completionHelper.attachEditText(
|
||||||
|
formRoot,
|
||||||
|
etContent,
|
||||||
|
false,
|
||||||
|
object : CompletionHelper.Callback2 {
|
||||||
override fun onTextUpdate() {
|
override fun onTextUpdate() {
|
||||||
updateTextCount()
|
updateTextCount()
|
||||||
}
|
}
|
||||||
|
@ -491,6 +462,6 @@ class ActPost : AppCompatActivity(),
|
||||||
scrollView.viewTreeObserver.addOnScrollChangedListener(scrollListener)
|
scrollView.viewTreeObserver.addOnScrollChangedListener(scrollListener)
|
||||||
|
|
||||||
etContent.contentMineTypeArray = AttachmentUploader.acceptableMimeTypes.toTypedArray()
|
etContent.contentMineTypeArray = AttachmentUploader.acceptableMimeTypes.toTypedArray()
|
||||||
etContent.commitContentListener = commitContentListener
|
etContent.contentCallback = { addAttachment(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ class ActText : AppCompatActivity() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.act_text, menu)
|
menuInflater.inflate(R.menu.act_text, menu)
|
||||||
return super.onCreateOptionsMenu(menu)
|
return super.onCreateOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,15 +348,13 @@ class CompletionHelper(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
et.setOnSelectionChangeListener(object : MyEditText.OnSelectionChangeListener {
|
|
||||||
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
|
|
||||||
if (selStart != selEnd) {
|
|
||||||
// 範囲選択されてるならポップアップは閉じる
|
// 範囲選択されてるならポップアップは閉じる
|
||||||
log.d("onSelectionChanged: range selected")
|
et.onSelectionChange = { selStart, selEnd ->
|
||||||
|
if (selStart != selEnd) {
|
||||||
|
log.d("onSelectionChange: range selected")
|
||||||
closeAcctPopup()
|
closeAcctPopup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
// 全然動いてなさそう…
|
// 全然動いてなさそう…
|
||||||
// et.setCustomSelectionActionModeCallback( action_mode_callback );
|
// et.setCustomSelectionActionModeCallback( action_mode_callback );
|
||||||
|
|
|
@ -105,7 +105,7 @@ open class TootApiResult(
|
||||||
}
|
}
|
||||||
|
|
||||||
// アカウント作成APIのdetailsを読むため、エラー応答のjsonオブジェクトを保持する
|
// アカウント作成APIのdetailsを読むため、エラー応答のjsonオブジェクトを保持する
|
||||||
var errorJson: JsonObject? = null
|
private var errorJson: JsonObject? = null
|
||||||
|
|
||||||
internal fun simplifyErrorHtml(
|
internal fun simplifyErrorHtml(
|
||||||
sv: String,
|
sv: String,
|
||||||
|
|
|
@ -379,7 +379,7 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||||
val result = Channel<Pair<TootInstance?, TootApiResult?>>()
|
val result = Channel<Pair<TootInstance?, TootApiResult?>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queuedRequest(
|
private fun queuedRequest(
|
||||||
allowPixelfed: Boolean,
|
allowPixelfed: Boolean,
|
||||||
get: suspend (cached: TootInstance?) -> Pair<TootInstance?, TootApiResult?>,
|
get: suspend (cached: TootInstance?) -> Pair<TootInstance?, TootApiResult?>,
|
||||||
) = QueuedRequest(allowPixelfed, get)
|
) = QueuedRequest(allowPixelfed, get)
|
||||||
|
|
|
@ -36,7 +36,7 @@ class TootReaction(
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun appendDomain(name: String, domain: String?) =
|
private fun appendDomain(name: String, domain: String?) =
|
||||||
if (domain?.isNotEmpty() == true) {
|
if (domain?.isNotEmpty() == true) {
|
||||||
"$name@$domain"
|
"$name@$domain"
|
||||||
} else {
|
} else {
|
||||||
|
@ -164,7 +164,7 @@ class TootReaction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun chooseUrl() = when {
|
private fun chooseUrl() = when {
|
||||||
PrefB.bpDisableEmojiAnimation(App1.pref) -> staticUrl
|
PrefB.bpDisableEmojiAnimation(App1.pref) -> staticUrl
|
||||||
else -> url
|
else -> url
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ColumnTask_Refresh(
|
||||||
private val bSilent: Boolean,
|
private val bSilent: Boolean,
|
||||||
val bBottom: Boolean,
|
val bBottom: Boolean,
|
||||||
internal val postedStatusId: EntityId? = null,
|
internal val postedStatusId: EntityId? = null,
|
||||||
internal val refreshAfterToot: Int = -1,
|
private val refreshAfterToot: Int = -1,
|
||||||
) : ColumnTask(
|
) : ColumnTask(
|
||||||
columnArg,
|
columnArg,
|
||||||
if (bBottom) ColumnTaskType.REFRESH_BOTTOM else ColumnTaskType.REFRESH_TOP
|
if (bBottom) ColumnTaskType.REFRESH_BOTTOM else ColumnTaskType.REFRESH_TOP
|
||||||
|
|
|
@ -18,7 +18,7 @@ class UserRelationLoader(val column: Column) {
|
||||||
|
|
||||||
val whoSet = HashSet<EntityId>()
|
val whoSet = HashSet<EntityId>()
|
||||||
val acctSet = HashSet<String>()
|
val acctSet = HashSet<String>()
|
||||||
val tagSet = HashSet<String>()
|
private val tagSet = HashSet<String>()
|
||||||
|
|
||||||
fun add(whoRef: TootAccountRef?) {
|
fun add(whoRef: TootAccountRef?) {
|
||||||
add(whoRef?.get())
|
add(whoRef?.get())
|
||||||
|
|
|
@ -80,7 +80,7 @@ class ColumnViewHolder(
|
||||||
lateinit var llColumnHeader: View
|
lateinit var llColumnHeader: View
|
||||||
lateinit var tvColumnIndex: TextView
|
lateinit var tvColumnIndex: TextView
|
||||||
lateinit var tvColumnStatus: TextView
|
lateinit var tvColumnStatus: TextView
|
||||||
lateinit var tvColumnContext: TextView
|
private lateinit var tvColumnContext: TextView
|
||||||
lateinit var ivColumnIcon: ImageView
|
lateinit var ivColumnIcon: ImageView
|
||||||
lateinit var tvColumnName: TextView
|
lateinit var tvColumnName: TextView
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ class ColumnViewHolder(
|
||||||
lateinit var btnQuickFilterVote: ImageButton
|
lateinit var btnQuickFilterVote: ImageButton
|
||||||
|
|
||||||
lateinit var llRefreshError: FrameLayout
|
lateinit var llRefreshError: FrameLayout
|
||||||
lateinit var ivRefreshError: ImageView
|
private lateinit var ivRefreshError: ImageView
|
||||||
lateinit var tvRefreshError: TextView
|
lateinit var tvRefreshError: TextView
|
||||||
|
|
||||||
lateinit var llListList: View
|
lateinit var llListList: View
|
||||||
|
|
|
@ -552,7 +552,7 @@ internal class DlgContextMenu(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onClickUpdateGroup(v: View): Boolean = when (v.id) {
|
private fun onClickUpdateGroup(v: View): Boolean = when (v.id) {
|
||||||
R.id.btnGroupStatusCrossAccount -> updateGroup(
|
R.id.btnGroupStatusCrossAccount -> updateGroup(
|
||||||
btnGroupStatusCrossAccount,
|
btnGroupStatusCrossAccount,
|
||||||
llGroupStatusCrossAccount,
|
llGroupStatusCrossAccount,
|
||||||
|
|
|
@ -775,7 +775,7 @@ class ItemViewHolder(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun _LinearLayout.inflateConversationIconOne() =
|
private fun _LinearLayout.inflateConversationIconOne() =
|
||||||
myNetworkImageView {
|
myNetworkImageView {
|
||||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||||
}.lparams(dip(24), dip(24)) {
|
}.lparams(dip(24), dip(24)) {
|
||||||
|
|
|
@ -324,7 +324,7 @@ fun ItemViewHolder.onClickEnqueteChoice(
|
||||||
TootPollsType.Mastodon -> client.request(
|
TootPollsType.Mastodon -> client.request(
|
||||||
"/api/v1/polls/${enquete.pollId}/votes",
|
"/api/v1/polls/${enquete.pollId}/votes",
|
||||||
jsonObject {
|
jsonObject {
|
||||||
put("choices", jp.juggler.util.jsonArray { add(idx) })
|
put("choices", jsonArray { add(idx) })
|
||||||
}.toPostRequestBuilder()
|
}.toPostRequestBuilder()
|
||||||
)
|
)
|
||||||
TootPollsType.FriendsNico -> client.request(
|
TootPollsType.FriendsNico -> client.request(
|
||||||
|
@ -406,7 +406,7 @@ fun ItemViewHolder.sendMultiple(
|
||||||
client.request(
|
client.request(
|
||||||
"/api/v1/polls/${enquete.pollId}/votes",
|
"/api/v1/polls/${enquete.pollId}/votes",
|
||||||
jsonObject {
|
jsonObject {
|
||||||
put("choices", jp.juggler.util.jsonArray {
|
put("choices", jsonArray {
|
||||||
enquete.items.forEachIndexed { index, choice ->
|
enquete.items.forEachIndexed { index, choice ->
|
||||||
if (choice.checked) add(index)
|
if (choice.checked) add(index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,8 @@ class StatusButtons(
|
||||||
private val colorAccent: Int
|
private val colorAccent: Int
|
||||||
get() = activity.attrColor(R.attr.colorImageButtonAccent)
|
get() = activity.attrColor(R.attr.colorImageButtonAccent)
|
||||||
|
|
||||||
var optionalButtonFirst: View? = null
|
private var optionalButtonFirst: View? = null
|
||||||
var optionalButtonCount = 0
|
private var optionalButtonCount = 0
|
||||||
var ti: TootInstance? = null
|
var ti: TootInstance? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
|
@ -472,7 +472,7 @@ class PushSubscriptionHelper(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun canSkipSubscriptionMastodon(
|
private suspend fun canSkipSubscriptionMastodon(
|
||||||
client: TootApiClient,
|
client: TootApiClient,
|
||||||
clientIdentifier: String,
|
clientIdentifier: String,
|
||||||
endpoint: String,
|
endpoint: String,
|
||||||
|
|
|
@ -3,7 +3,7 @@ package jp.juggler.subwaytooter.span
|
||||||
import android.text.TextPaint
|
import android.text.TextPaint
|
||||||
import android.text.style.CharacterStyle
|
import android.text.style.CharacterStyle
|
||||||
|
|
||||||
class HighlightSpan(val colorFg: Int, val colorBg: Int) : CharacterStyle() {
|
class HighlightSpan(private val colorFg: Int, val colorBg: Int) : CharacterStyle() {
|
||||||
|
|
||||||
override fun updateDrawState(ds: TextPaint) {
|
override fun updateDrawState(ds: TextPaint) {
|
||||||
if (colorFg != 0) ds.color = colorFg
|
if (colorFg != 0) ds.color = colorFg
|
||||||
|
|
|
@ -31,7 +31,7 @@ class MyClickableSpan(val linkInfo: LinkInfo) : ClickableSpan() {
|
||||||
var showLinkUnderline = true
|
var showLinkUnderline = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val colorFg: Int
|
private val colorFg: Int
|
||||||
val colorBg: Int
|
val colorBg: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
|
@ -223,7 +223,7 @@ class AttachmentPicker(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun performCapture(action: String, errorCaption: String) {
|
private fun performCapture(action: String, errorCaption: String) {
|
||||||
try {
|
try {
|
||||||
arCapture.launch(Intent(action))
|
arCapture.launch(Intent(action))
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
|
|
|
@ -69,10 +69,10 @@ class PostImpl(
|
||||||
|
|
||||||
private var visibilityChecked: TootVisibility? = null
|
private var visibilityChecked: TootVisibility? = null
|
||||||
|
|
||||||
var bConfirmTag: Boolean = false
|
private var bConfirmTag: Boolean = false
|
||||||
var bConfirmAccount: Boolean = false
|
var bConfirmAccount: Boolean = false
|
||||||
var bConfirmRedraft: Boolean = false
|
private var bConfirmRedraft: Boolean = false
|
||||||
var bConfirmTagCharacter: Boolean = false
|
private var bConfirmTagCharacter: Boolean = false
|
||||||
|
|
||||||
private val choiceMaxChars = when {
|
private val choiceMaxChars = when {
|
||||||
account.isMisskey -> 15
|
account.isMisskey -> 15
|
||||||
|
@ -229,9 +229,9 @@ class PostImpl(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultStatus: TootStatus? = null
|
private var resultStatus: TootStatus? = null
|
||||||
var resultCredentialTmp: TootAccount? = null
|
private var resultCredentialTmp: TootAccount? = null
|
||||||
var resultScheduledStatusSucceeded = false
|
private var resultScheduledStatusSucceeded = false
|
||||||
|
|
||||||
private suspend fun getCredential(
|
private suspend fun getCredential(
|
||||||
client: TootApiClient,
|
client: TootApiClient,
|
||||||
|
|
|
@ -2,23 +2,53 @@ package jp.juggler.subwaytooter.view
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.view.inputmethod.EditorInfoCompat
|
import android.net.Uri
|
||||||
import androidx.core.view.inputmethod.InputConnectionCompat
|
|
||||||
import androidx.appcompat.widget.AppCompatEditText
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.View
|
||||||
import android.view.inputmethod.InputConnection
|
import androidx.appcompat.widget.AppCompatEditText
|
||||||
|
import androidx.core.view.ContentInfoCompat
|
||||||
|
import androidx.core.view.OnReceiveContentListener
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import jp.juggler.util.LogCategory
|
import jp.juggler.util.LogCategory
|
||||||
|
|
||||||
|
|
||||||
class MyEditText : AppCompatEditText {
|
class MyEditText : AppCompatEditText {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = LogCategory("MyEditText")
|
private val log = LogCategory("MyEditText")
|
||||||
|
val MIME_TYPES = arrayOf("image/*")
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mOnSelectionChangeListener: OnSelectionChangeListener? = null
|
// 選択範囲変更リスナ
|
||||||
|
var onSelectionChange: ((selStart: Int, selEnd: Int) -> Unit)? = null
|
||||||
|
|
||||||
|
// キーボードやDnDから画像を挿入するリスナ
|
||||||
|
var contentCallback: ((Uri) -> Unit)? = null
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// IMEから画像を送られてくることがあるらしい
|
||||||
|
|
||||||
|
var contentMineTypeArray: Array<String>? = null
|
||||||
|
|
||||||
|
private val receiveContentListener = object : OnReceiveContentListener {
|
||||||
|
override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat {
|
||||||
|
// 受け付けない状況では何も受け取らずに残りを返す
|
||||||
|
val contentCallback = contentCallback ?: return payload
|
||||||
|
|
||||||
|
val pair = payload.partition { item -> item.uri != null }
|
||||||
|
val uriContent = pair.first
|
||||||
|
val remaining = pair.second
|
||||||
|
if (uriContent != null) {
|
||||||
|
val clip = uriContent.clip
|
||||||
|
for (i in 0 until clip.itemCount) {
|
||||||
|
val uri = clip.getItemAt(i).uri
|
||||||
|
contentCallback(uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaining
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(context: Context) : super(context)
|
constructor(context: Context) : super(context)
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||||
|
@ -28,20 +58,16 @@ class MyEditText : AppCompatEditText {
|
||||||
defStyleAttr
|
defStyleAttr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
ViewCompat.setOnReceiveContentListener(this, MIME_TYPES, receiveContentListener)
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// 選択範囲変更イベントをコールバックに渡す
|
// 選択範囲変更の傍受
|
||||||
|
|
||||||
interface OnSelectionChangeListener {
|
|
||||||
fun onSelectionChanged(selStart: Int, selEnd: Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnSelectionChangeListener(listener: OnSelectionChangeListener) {
|
|
||||||
mOnSelectionChangeListener = listener
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
|
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
|
||||||
super.onSelectionChanged(selStart, selEnd)
|
super.onSelectionChanged(selStart, selEnd)
|
||||||
mOnSelectionChangeListener?.onSelectionChanged(selStart, selEnd)
|
onSelectionChange?.invoke(selStart, selEnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
@ -61,26 +87,4 @@ class MyEditText : AppCompatEditText {
|
||||||
// at android.view.View.dispatchTouchEvent (View.java:9303)
|
// at android.view.View.dispatchTouchEvent (View.java:9303)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// IMEから画像を送られてくることがあるらしい
|
|
||||||
|
|
||||||
var commitContentListener: InputConnectionCompat.OnCommitContentListener? = null
|
|
||||||
var contentMineTypeArray: Array<String>? = null
|
|
||||||
|
|
||||||
override fun onCreateInputConnection(outAttrs: EditorInfo?): InputConnection? {
|
|
||||||
|
|
||||||
log.d("onCreateInputConnection: listener=$commitContentListener")
|
|
||||||
|
|
||||||
val superIc = super.onCreateInputConnection(outAttrs)
|
|
||||||
|
|
||||||
val listener = commitContentListener
|
|
||||||
val mimeArray = contentMineTypeArray
|
|
||||||
return if (listener == null || mimeArray == null || outAttrs == null) {
|
|
||||||
superIc
|
|
||||||
} else {
|
|
||||||
EditorInfoCompat.setContentMimeTypes(outAttrs, mimeArray)
|
|
||||||
superIc?.let { InputConnectionCompat.createWrapper(it, outAttrs, listener) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package jp.juggler.util
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
|
import androidx.annotation.IntRange
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
// SQLite にBooleanをそのまま保存することはできないのでInt型との変換が必要になる
|
// SQLite にBooleanをそのまま保存することはできないのでInt型との変換が必要になる
|
||||||
|
@ -19,16 +20,21 @@ fun Int.i2b() = this != 0
|
||||||
// getBoolean(getColumnIndex(key))
|
// getBoolean(getColumnIndex(key))
|
||||||
|
|
||||||
fun Cursor.getInt(key: String) =
|
fun Cursor.getInt(key: String) =
|
||||||
getInt(getColumnIndex(key))
|
getColumnIndex(key).takeIf { it >= 0 }?.let { getInt(it) }
|
||||||
|
?: error("getInt: missing column named $key")
|
||||||
|
|
||||||
fun Cursor.getIntOrNull(idx: Int) =
|
fun Cursor.getIntOrNull(@IntRange(from = 0) idx: Int) = when {
|
||||||
if (isNull(idx)) null else getInt(idx)
|
idx < 0 -> error("getIntOrNull: invalid index $idx")
|
||||||
|
isNull(idx) -> null
|
||||||
|
else -> getInt(idx)
|
||||||
|
}
|
||||||
|
|
||||||
fun Cursor.getIntOrNull(key: String) =
|
fun Cursor.getIntOrNull(key: String) =
|
||||||
getIntOrNull(getColumnIndex(key))
|
getColumnIndex(key).takeIf { it >= 0 }?.let { getIntOrNull(it) }
|
||||||
|
|
||||||
fun Cursor.getLong(key: String) =
|
fun Cursor.getLong(key: String) =
|
||||||
getLong(getColumnIndex(key))
|
getColumnIndex(key).takeIf { it >= 0 }?.let { getLong(it) }
|
||||||
|
?: error("getLong: missing column named $key")
|
||||||
|
|
||||||
//fun Cursor.getLongOrNull(idx:Int) =
|
//fun Cursor.getLongOrNull(idx:Int) =
|
||||||
// if(isNull(idx)) null else getLong(idx)
|
// if(isNull(idx)) null else getLong(idx)
|
||||||
|
@ -37,7 +43,8 @@ fun Cursor.getLong(key: String) =
|
||||||
// getLongOrNull(getColumnIndex(key))
|
// getLongOrNull(getColumnIndex(key))
|
||||||
|
|
||||||
fun Cursor.getString(key: String): String =
|
fun Cursor.getString(key: String): String =
|
||||||
getString(getColumnIndex(key))
|
getColumnIndex(key).takeIf { it >= 0 }?.let { getString(it)!! }
|
||||||
|
?: error("getString: missing column named $key")
|
||||||
|
|
||||||
fun Cursor.getStringOrNull(keyIdx: Int) =
|
fun Cursor.getStringOrNull(keyIdx: Int) =
|
||||||
if (isNull(keyIdx)) null else getString(keyIdx)
|
if (isNull(keyIdx)) null else getString(keyIdx)
|
||||||
|
@ -69,7 +76,7 @@ class ColumnMeta(
|
||||||
|
|
||||||
class List(
|
class List(
|
||||||
val table: String,
|
val table: String,
|
||||||
val initialVersion: Int,
|
private val initialVersion: Int,
|
||||||
var createExtra: () -> Array<String> = { emptyArray() },
|
var createExtra: () -> Array<String> = { emptyArray() },
|
||||||
var deleteBeforeCreate: Boolean = false,
|
var deleteBeforeCreate: Boolean = false,
|
||||||
) : ArrayList<ColumnMeta>() {
|
) : ArrayList<ColumnMeta>() {
|
||||||
|
@ -143,15 +150,9 @@ fun ContentValues.put(key: ColumnMeta, v: Float?) = put(key.name, v)
|
||||||
fun ContentValues.put(key: ColumnMeta, v: Double?) = put(key.name, v)
|
fun ContentValues.put(key: ColumnMeta, v: Double?) = put(key.name, v)
|
||||||
fun ContentValues.put(key: ColumnMeta, v: ByteArray?) = put(key.name, v)
|
fun ContentValues.put(key: ColumnMeta, v: ByteArray?) = put(key.name, v)
|
||||||
|
|
||||||
fun Cursor.getInt(key: ColumnMeta) = getInt(getColumnIndex(key.name))
|
fun Cursor.getInt(key: ColumnMeta) = getInt(key.name)
|
||||||
|
fun Cursor.getBoolean(key: ColumnMeta) = getInt(key.name).i2b()
|
||||||
fun Cursor.getBoolean(key: ColumnMeta) = getInt(key).i2b()
|
fun Cursor.getLong(key: ColumnMeta) = getLong(key.name)
|
||||||
fun Cursor.getLong(key: ColumnMeta) = getLong(getColumnIndex(key.name))
|
fun Cursor.getIntOrNull(key: ColumnMeta) = getIntOrNull(key.name)
|
||||||
|
fun Cursor.getString(key: ColumnMeta): String = getString(key.name)
|
||||||
@Suppress("unused")
|
fun Cursor.getStringOrNull(key: ColumnMeta): String? = getStringOrNull(key.name)
|
||||||
fun Cursor.getIntOrNull(key: ColumnMeta) = getIntOrNull(getColumnIndex(key.name))
|
|
||||||
fun Cursor.getString(key: ColumnMeta): String = getString(getColumnIndex(key.name))
|
|
||||||
fun Cursor.getStringOrNull(key: ColumnMeta): String? {
|
|
||||||
val idx = key.getIndex(this)
|
|
||||||
return if (isNull(idx)) null else getString(idx)
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class LogCategory(category: String) {
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// string
|
// string
|
||||||
|
|
||||||
fun msg(priority: Int, msg: String): Boolean {
|
private fun msg(priority: Int, msg: String): Boolean {
|
||||||
Log.println(priority, tag, msg)
|
Log.println(priority, tag, msg)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ class LogCategory(category: String) {
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Resources.getString()
|
// Resources.getString()
|
||||||
|
|
||||||
fun msg(priority: Int, res: Resources, @StringRes stringId: Int, args: Array<out Any?>) =
|
private fun msg(priority: Int, res: Resources, @StringRes stringId: Int, args: Array<out Any?>) =
|
||||||
msg(priority, res.getString(stringId, *args))
|
msg(priority, res.getString(stringId, *args))
|
||||||
|
|
||||||
fun e(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
fun e(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
||||||
|
@ -58,7 +58,7 @@ class LogCategory(category: String) {
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Throwable + string
|
// Throwable + string
|
||||||
|
|
||||||
fun msg(priority: Int, ex: Throwable, caption: String = "exception.") =
|
private fun msg(priority: Int, ex: Throwable, caption: String = "exception.") =
|
||||||
msg(priority, ex.withCaption(caption))
|
msg(priority, ex.withCaption(caption))
|
||||||
|
|
||||||
fun e(ex: Throwable, caption: String = "exception") = msg(Log.ERROR, ex, caption)
|
fun e(ex: Throwable, caption: String = "exception") = msg(Log.ERROR, ex, caption)
|
||||||
|
|
19
build.gradle
19
build.gradle
|
@ -1,19 +1,22 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
|
|
||||||
ext.min_sdk_version = 21
|
ext.min_sdk_version = 21
|
||||||
ext.target_sdk_version = 30
|
ext.target_sdk_version = 31
|
||||||
ext.compile_sdk_version = 30
|
ext.compile_sdk_version = 31
|
||||||
|
|
||||||
ext.appcompat_version='1.3.0'
|
ext.appcompat_version='1.3.1'
|
||||||
ext.lifecycle_version='2.3.1'
|
ext.lifecycle_version="2.4.0-rc01"
|
||||||
|
ext.arch_version = "2.1.0"
|
||||||
|
|
||||||
ext.kotlin_version = '1.5.20'
|
ext.kotlin_version = '1.5.31'
|
||||||
ext.kotlinx_coroutines_version = '1.5.0'
|
ext.kotlinx_coroutines_version = '1.5.2'
|
||||||
ext.anko_version='0.10.8'
|
ext.anko_version='0.10.8'
|
||||||
|
|
||||||
ext.junit_version='4.13.2'
|
ext.junit_version='4.13.2'
|
||||||
|
|
||||||
ext.detekt_version='1.18.0'
|
ext.detekt_version='1.18.1'
|
||||||
|
|
||||||
|
ext.compose_version = '1.0.4'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
@ -21,7 +24,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.2.2'
|
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
classpath 'com.google.gms:google-services:4.3.10'
|
||||||
|
|
||||||
//noinspection DifferentKotlinGradleVersion
|
//noinspection DifferentKotlinGradleVersion
|
||||||
|
|
|
@ -33,11 +33,11 @@ import androidx.annotation.NonNull;
|
||||||
*/
|
*/
|
||||||
class AlphaPatternDrawable extends Drawable {
|
class AlphaPatternDrawable extends Drawable {
|
||||||
|
|
||||||
private int rectangleSize;
|
private final int rectangleSize;
|
||||||
|
|
||||||
private Paint paint = new Paint();
|
private final Paint paint = new Paint();
|
||||||
private Paint paintWhite = new Paint();
|
private final Paint paintWhite = new Paint();
|
||||||
private Paint paintGray = new Paint();
|
private final Paint paintGray = new Paint();
|
||||||
|
|
||||||
private int numRectanglesHorizontal;
|
private int numRectanglesHorizontal;
|
||||||
private int numRectanglesVertical;
|
private int numRectanglesVertical;
|
||||||
|
@ -55,25 +55,30 @@ class AlphaPatternDrawable extends Drawable {
|
||||||
paintGray.setColor(0xFFCBCBCB);
|
paintGray.setColor(0xFFCBCBCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void draw( @NonNull Canvas canvas ){
|
@Override
|
||||||
|
public void draw(@NonNull Canvas canvas) {
|
||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
canvas.drawBitmap(bitmap, null, getBounds(), paint);
|
canvas.drawBitmap(bitmap, null, getBounds(), paint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getOpacity(){
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
return PixelFormat.UNKNOWN;
|
return PixelFormat.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void setAlpha( int alpha ){
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
throw new UnsupportedOperationException("Alpha is not supported by this drawable.");
|
throw new UnsupportedOperationException("Alpha is not supported by this drawable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void setColorFilter( ColorFilter cf ){
|
@Override
|
||||||
|
public void setColorFilter(ColorFilter cf) {
|
||||||
throw new UnsupportedOperationException("ColorFilter is not supported by this drawable.");
|
throw new UnsupportedOperationException("ColorFilter is not supported by this drawable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onBoundsChange( Rect bounds ){
|
@Override
|
||||||
|
protected void onBoundsChange(Rect bounds) {
|
||||||
super.onBoundsChange(bounds);
|
super.onBoundsChange(bounds);
|
||||||
int height = bounds.height();
|
int height = bounds.height();
|
||||||
int width = bounds.width();
|
int width = bounds.width();
|
||||||
|
|
|
@ -19,18 +19,19 @@ package com.jrummyapps.android.colorpicker;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import androidx.core.graphics.ColorUtils;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.core.graphics.ColorUtils;
|
||||||
|
|
||||||
class ColorPaletteAdapter extends BaseAdapter {
|
class ColorPaletteAdapter extends BaseAdapter {
|
||||||
|
|
||||||
/*package*/ final OnColorSelectedListener listener;
|
/*package*/ final OnColorSelectedListener listener;
|
||||||
/*package*/ final int[] colors;
|
/*package*/ final int[] colors;
|
||||||
/*package*/ int selectedPosition;
|
/*package*/ int selectedPosition;
|
||||||
/*package*/ int colorShape;
|
/*package*/ final int colorShape;
|
||||||
|
|
||||||
ColorPaletteAdapter(OnColorSelectedListener listener,
|
ColorPaletteAdapter(OnColorSelectedListener listener,
|
||||||
int[] colors,
|
int[] colors,
|
||||||
|
@ -42,19 +43,23 @@ class ColorPaletteAdapter extends BaseAdapter {
|
||||||
this.colorShape = colorShape;
|
this.colorShape = colorShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getCount() {
|
@Override
|
||||||
|
public int getCount() {
|
||||||
return colors.length;
|
return colors.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Object getItem(int position) {
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
return colors[position];
|
return colors[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public long getItemId(int position) {
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public View getView(int position, View convertView, ViewGroup parent) {
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
final ViewHolder holder;
|
final ViewHolder holder;
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
holder = new ViewHolder(parent.getContext());
|
holder = new ViewHolder(parent.getContext());
|
||||||
|
@ -78,10 +83,10 @@ class ColorPaletteAdapter extends BaseAdapter {
|
||||||
|
|
||||||
private final class ViewHolder {
|
private final class ViewHolder {
|
||||||
|
|
||||||
View view;
|
final View view;
|
||||||
ColorPanelView colorPanelView;
|
final ColorPanelView colorPanelView;
|
||||||
ImageView imageView;
|
final ImageView imageView;
|
||||||
int originalBorderColor;
|
final int originalBorderColor;
|
||||||
|
|
||||||
ViewHolder(Context context) {
|
ViewHolder(Context context) {
|
||||||
int layoutResId;
|
int layoutResId;
|
||||||
|
@ -91,8 +96,8 @@ class ColorPaletteAdapter extends BaseAdapter {
|
||||||
layoutResId = R.layout.cpv_color_item_circle;
|
layoutResId = R.layout.cpv_color_item_circle;
|
||||||
}
|
}
|
||||||
view = View.inflate(context, layoutResId, null);
|
view = View.inflate(context, layoutResId, null);
|
||||||
colorPanelView = (ColorPanelView) view.findViewById(R.id.cpv_color_panel_view);
|
colorPanelView = view.findViewById(R.id.cpv_color_panel_view);
|
||||||
imageView = (ImageView) view.findViewById(R.id.cpv_color_image_view);
|
imageView = view.findViewById(R.id.cpv_color_image_view);
|
||||||
originalBorderColor = colorPanelView.getBorderColor();
|
originalBorderColor = colorPanelView.getBorderColor();
|
||||||
view.setTag(this);
|
view.setTag(this);
|
||||||
}
|
}
|
||||||
|
@ -117,20 +122,16 @@ class ColorPaletteAdapter extends BaseAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setOnClickListener(final int position) {
|
private void setOnClickListener(final int position) {
|
||||||
colorPanelView.setOnClickListener(new View.OnClickListener() {
|
colorPanelView.setOnClickListener(v -> {
|
||||||
@Override public void onClick(View v) {
|
|
||||||
if (selectedPosition != position) {
|
if (selectedPosition != position) {
|
||||||
selectedPosition = position;
|
selectedPosition = position;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
listener.onColorSelected(colors[position]);
|
listener.onColorSelected(colors[position]);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
colorPanelView.setOnLongClickListener(new View.OnLongClickListener() {
|
colorPanelView.setOnLongClickListener(v -> {
|
||||||
@Override public boolean onLongClick(View v) {
|
|
||||||
colorPanelView.showHint();
|
colorPanelView.showHint();
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,22 +141,22 @@ public class ColorPanelView extends View {
|
||||||
} else if (shape == ColorShape.CIRCLE) {
|
} else if (shape == ColorShape.CIRCLE) {
|
||||||
final int outerRadius = getMeasuredWidth() / 2;
|
final int outerRadius = getMeasuredWidth() / 2;
|
||||||
if (borderWidthPx > 0) {
|
if (borderWidthPx > 0) {
|
||||||
canvas.drawCircle(getMeasuredWidth() / 2,
|
canvas.drawCircle(getMeasuredWidth() / 2f,
|
||||||
getMeasuredHeight() / 2,
|
getMeasuredHeight() / 2f,
|
||||||
outerRadius,
|
outerRadius,
|
||||||
borderPaint);
|
borderPaint);
|
||||||
}
|
}
|
||||||
if (Color.alpha(color) < 255) {
|
if (Color.alpha(color) < 255) {
|
||||||
canvas.drawCircle(getMeasuredWidth() / 2,
|
canvas.drawCircle(getMeasuredWidth() / 2f,
|
||||||
getMeasuredHeight() / 2,
|
getMeasuredHeight() / 2f,
|
||||||
outerRadius - borderWidthPx, alphaPaint);
|
outerRadius - borderWidthPx, alphaPaint);
|
||||||
}
|
}
|
||||||
if (showOldColor) {
|
if (showOldColor) {
|
||||||
canvas.drawArc(centerRect, 90, 180, true, originalPaint);
|
canvas.drawArc(centerRect, 90, 180, true, originalPaint);
|
||||||
canvas.drawArc(centerRect, 270, 180, true, colorPaint);
|
canvas.drawArc(centerRect, 270, 180, true, colorPaint);
|
||||||
} else {
|
} else {
|
||||||
canvas.drawCircle(getMeasuredWidth() / 2,
|
canvas.drawCircle(getMeasuredWidth() / 2f,
|
||||||
getMeasuredHeight() / 2,
|
getMeasuredHeight() / 2f,
|
||||||
outerRadius - borderWidthPx,
|
outerRadius - borderWidthPx,
|
||||||
colorPaint);
|
colorPaint);
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,7 @@ public class ColorPanelView extends View {
|
||||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
setMeasuredDimension(width, height);
|
setMeasuredDimension(width, height);
|
||||||
} else if (shape == ColorShape.CIRCLE) {
|
} else if (shape == ColorShape.CIRCLE) {
|
||||||
|
//noinspection SuspiciousNameCombination
|
||||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||||
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
|
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,19 +19,12 @@ package com.jrummyapps.android.colorpicker;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.DialogFragment;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.ColorInt;
|
|
||||||
import androidx.annotation.IntDef;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.core.graphics.ColorUtils;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputFilter;
|
import android.text.InputFilter;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
@ -50,6 +43,7 @@ import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.jrummyapps.android.colorpicker.ColorPickerView.OnColorChangedListener;
|
import com.jrummyapps.android.colorpicker.ColorPickerView.OnColorChangedListener;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
@ -57,6 +51,15 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.core.graphics.ColorUtils;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>A dialog to pick a color.</p>
|
* <p>A dialog to pick a color.</p>
|
||||||
*
|
*
|
||||||
|
@ -68,7 +71,9 @@ import java.util.Locale;
|
||||||
* ColorPickerDialog.newBuilder().show(activity);
|
* ColorPickerDialog.newBuilder().show(activity);
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ColorPickerDialog extends DialogFragment implements OnTouchListener, OnColorChangedListener, TextWatcher {
|
public class ColorPickerDialog
|
||||||
|
extends DialogFragment
|
||||||
|
implements OnTouchListener, OnColorChangedListener, TextWatcher {
|
||||||
|
|
||||||
private static final String ARG_ID = "id";
|
private static final String ARG_ID = "id";
|
||||||
private static final String ARG_TYPE = "dialogType";
|
private static final String ARG_TYPE = "dialogType";
|
||||||
|
@ -123,7 +128,8 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
ColorPickerDialogListener colorPickerDialogListener;
|
ColorPickerDialogListener colorPickerDialogListener;
|
||||||
FrameLayout rootView;
|
FrameLayout rootView;
|
||||||
int[] presets;
|
int[] presets;
|
||||||
@ColorInt int color;
|
@ColorInt
|
||||||
|
int color;
|
||||||
int dialogType;
|
int dialogType;
|
||||||
int dialogId;
|
int dialogId;
|
||||||
boolean showColorShades;
|
boolean showColorShades;
|
||||||
|
@ -142,50 +148,58 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
boolean showAlphaSlider;
|
boolean showAlphaSlider;
|
||||||
private boolean fromEditText;
|
private boolean fromEditText;
|
||||||
|
|
||||||
@Override public void onAttach(Activity activity) {
|
@Override
|
||||||
super.onAttach(activity);
|
public void onAttach(@NonNull Context context) {
|
||||||
if (colorPickerDialogListener == null && activity instanceof ColorPickerDialogListener) {
|
super.onAttach(context);
|
||||||
colorPickerDialogListener = (ColorPickerDialogListener) activity;
|
if (colorPickerDialogListener == null && context instanceof ColorPickerDialogListener) {
|
||||||
|
colorPickerDialogListener = (ColorPickerDialogListener) context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
|
@NonNull
|
||||||
dialogId = getArguments().getInt(ARG_ID);
|
@Override
|
||||||
showAlphaSlider = getArguments().getBoolean(ARG_ALPHA);
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
showColorShades = getArguments().getBoolean(ARG_SHOW_COLOR_SHADES);
|
Bundle args = getArguments();
|
||||||
colorShape = getArguments().getInt(ARG_COLOR_SHAPE);
|
if (args == null) throw new RuntimeException("onCreateDialog: args is null");
|
||||||
|
Context context = getContext();
|
||||||
|
if (context == null) throw new RuntimeException("onCreateDialog: context is null");
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity == null) throw new RuntimeException("onCreateDialog: activity is null");
|
||||||
|
|
||||||
|
dialogId = args.getInt(ARG_ID);
|
||||||
|
showAlphaSlider = args.getBoolean(ARG_ALPHA);
|
||||||
|
showColorShades = args.getBoolean(ARG_SHOW_COLOR_SHADES);
|
||||||
|
colorShape = args.getInt(ARG_COLOR_SHAPE);
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
color = getArguments().getInt(ARG_COLOR);
|
color = args.getInt(ARG_COLOR);
|
||||||
dialogType = getArguments().getInt(ARG_TYPE);
|
dialogType = args.getInt(ARG_TYPE);
|
||||||
} else {
|
} else {
|
||||||
color = savedInstanceState.getInt(ARG_COLOR);
|
color = savedInstanceState.getInt(ARG_COLOR);
|
||||||
dialogType = savedInstanceState.getInt(ARG_TYPE);
|
dialogType = savedInstanceState.getInt(ARG_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
rootView = new FrameLayout(getActivity());
|
|
||||||
|
rootView = new FrameLayout(activity);
|
||||||
if (dialogType == TYPE_CUSTOM) {
|
if (dialogType == TYPE_CUSTOM) {
|
||||||
rootView.addView(createPickerView());
|
rootView.addView(createPickerView());
|
||||||
} else if (dialogType == TYPE_PRESETS) {
|
} else if (dialogType == TYPE_PRESETS) {
|
||||||
rootView.addView(createPresetsView());
|
rootView.addView(createPresetsView());
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
||||||
.setView(rootView)
|
.setView(rootView)
|
||||||
.setPositiveButton(R.string.cpv_select, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.cpv_select, (dialog, which) ->
|
||||||
@Override public void onClick(DialogInterface dialog, int which) {
|
colorPickerDialogListener.onColorSelected(dialogId, color));
|
||||||
colorPickerDialogListener.onColorSelected(dialogId, color);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
int dialogTitleStringRes = getArguments().getInt(ARG_DIALOG_TITLE);
|
int dialogTitleStringRes = args.getInt(ARG_DIALOG_TITLE);
|
||||||
if (dialogTitleStringRes != 0) {
|
if (dialogTitleStringRes != 0) {
|
||||||
builder.setTitle(dialogTitleStringRes);
|
builder.setTitle(dialogTitleStringRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int neutralButtonStringRes;
|
int neutralButtonStringRes;
|
||||||
if (dialogType == TYPE_CUSTOM && getArguments().getBoolean(ARG_ALLOW_PRESETS)) {
|
if (dialogType == TYPE_CUSTOM && args.getBoolean(ARG_ALLOW_PRESETS)) {
|
||||||
neutralButtonStringRes = R.string.cpv_presets;
|
neutralButtonStringRes = R.string.cpv_presets;
|
||||||
} else if (dialogType == TYPE_PRESETS && getArguments().getBoolean(ARG_ALLOW_CUSTOM)) {
|
} else if (dialogType == TYPE_PRESETS && args.getBoolean(ARG_ALLOW_CUSTOM)) {
|
||||||
neutralButtonStringRes = R.string.cpv_custom;
|
neutralButtonStringRes = R.string.cpv_custom;
|
||||||
} else {
|
} else {
|
||||||
neutralButtonStringRes = 0;
|
neutralButtonStringRes = 0;
|
||||||
|
@ -198,21 +212,22 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onStart() {
|
@Override
|
||||||
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
AlertDialog dialog = (AlertDialog) getDialog();
|
AlertDialog dialog = (AlertDialog) getDialog();
|
||||||
|
|
||||||
// http://stackoverflow.com/a/16972670/1048340
|
// http://stackoverflow.com/a/16972670/1048340
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
dialog.getWindow()
|
dialog.getWindow()
|
||||||
.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||||
|
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||||
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||||
|
|
||||||
// Do not dismiss the dialog when clicking the neutral button.
|
// Do not dismiss the dialog when clicking the neutral button.
|
||||||
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
|
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
|
||||||
if (neutralButton != null) {
|
if (neutralButton != null) {
|
||||||
neutralButton.setOnClickListener(new View.OnClickListener() {
|
neutralButton.setOnClickListener(v -> {
|
||||||
@Override public void onClick(View v) {
|
|
||||||
rootView.removeAllViews();
|
rootView.removeAllViews();
|
||||||
switch (dialogType) {
|
switch (dialogType) {
|
||||||
case TYPE_CUSTOM:
|
case TYPE_CUSTOM:
|
||||||
|
@ -225,17 +240,18 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
((Button) v).setText(R.string.cpv_presets);
|
((Button) v).setText(R.string.cpv_presets);
|
||||||
rootView.addView(createPickerView());
|
rootView.addView(createPickerView());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onDismiss(DialogInterface dialog) {
|
@Override
|
||||||
|
public void onDismiss(@NonNull DialogInterface dialog) {
|
||||||
super.onDismiss(dialog);
|
super.onDismiss(dialog);
|
||||||
colorPickerDialogListener.onDialogDismissed(dialogId);
|
colorPickerDialogListener.onDialogDismissed(dialogId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onSaveInstanceState(Bundle outState) {
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
outState.putInt(ARG_COLOR, color);
|
outState.putInt(ARG_COLOR, color);
|
||||||
outState.putInt(ARG_TYPE, dialogType);
|
outState.putInt(ARG_TYPE, dialogType);
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
@ -244,8 +260,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set the callback
|
* Set the callback
|
||||||
*
|
*
|
||||||
* @param colorPickerDialogListener
|
* @param colorPickerDialogListener The callback invoked when a color is selected or the dialog is dismissed.
|
||||||
* The callback invoked when a color is selected or the dialog is dismissed.
|
|
||||||
*/
|
*/
|
||||||
public void setColorPickerDialogListener(ColorPickerDialogListener colorPickerDialogListener) {
|
public void setColorPickerDialogListener(ColorPickerDialogListener colorPickerDialogListener) {
|
||||||
this.colorPickerDialogListener = colorPickerDialogListener;
|
this.colorPickerDialogListener = colorPickerDialogListener;
|
||||||
|
@ -254,6 +269,11 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
// region Custom Picker
|
// region Custom Picker
|
||||||
|
|
||||||
View createPickerView() {
|
View createPickerView() {
|
||||||
|
Bundle args = getArguments();
|
||||||
|
if (args == null) throw new RuntimeException("createPickerView: args is null");
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
if (activity == null) throw new RuntimeException("createPickerView: activity is null");
|
||||||
|
|
||||||
View contentView = View.inflate(getActivity(), R.layout.cpv_dialog_color_picker, null);
|
View contentView = View.inflate(getActivity(), R.layout.cpv_dialog_color_picker, null);
|
||||||
colorPicker = contentView.findViewById(R.id.cpv_color_picker_view);
|
colorPicker = contentView.findViewById(R.id.cpv_color_picker_view);
|
||||||
ColorPanelView oldColorPanel = contentView.findViewById(R.id.cpv_color_panel_old);
|
ColorPanelView oldColorPanel = contentView.findViewById(R.id.cpv_color_panel_old);
|
||||||
|
@ -263,8 +283,10 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final TypedValue value = new TypedValue();
|
final TypedValue value = new TypedValue();
|
||||||
TypedArray typedArray =
|
TypedArray typedArray = activity.obtainStyledAttributes(
|
||||||
getActivity().obtainStyledAttributes(value.data, new int[]{android.R.attr.textColorPrimary});
|
value.data,
|
||||||
|
new int[]{android.R.attr.textColorPrimary}
|
||||||
|
);
|
||||||
int arrowColor = typedArray.getColor(0, Color.BLACK);
|
int arrowColor = typedArray.getColor(0, Color.BLACK);
|
||||||
typedArray.recycle();
|
typedArray.recycle();
|
||||||
arrowRight.setColorFilter(arrowColor);
|
arrowRight.setColorFilter(arrowColor);
|
||||||
|
@ -272,7 +294,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
}
|
}
|
||||||
|
|
||||||
colorPicker.setAlphaSliderVisible(showAlphaSlider);
|
colorPicker.setAlphaSliderVisible(showAlphaSlider);
|
||||||
oldColorPanel.setColor(getArguments().getInt(ARG_COLOR));
|
oldColorPanel.setColor(args.getInt(ARG_COLOR));
|
||||||
colorPicker.setColor(color, true);
|
colorPicker.setColor(color, true);
|
||||||
newColorPanel.setColor(color);
|
newColorPanel.setColor(color);
|
||||||
setHex(color);
|
setHex(color);
|
||||||
|
@ -281,37 +303,35 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
hexEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(6)});
|
hexEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(6)});
|
||||||
}
|
}
|
||||||
|
|
||||||
newColorPanel.setOnClickListener(new View.OnClickListener() {
|
newColorPanel.setOnClickListener(v -> {
|
||||||
@Override public void onClick(View v) {
|
|
||||||
if (newColorPanel.getColor() == color) {
|
if (newColorPanel.getColor() == color) {
|
||||||
colorPickerDialogListener.onColorSelected(dialogId, color);
|
colorPickerDialogListener.onColorSelected(dialogId, color);
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
contentView.setOnTouchListener(this);
|
contentView.setOnTouchListener(this);
|
||||||
colorPicker.setOnColorChangedListener(this);
|
colorPicker.setOnColorChangedListener(this);
|
||||||
hexEditText.addTextChangedListener(this);
|
hexEditText.addTextChangedListener(this);
|
||||||
|
|
||||||
hexEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
hexEditText.setOnFocusChangeListener((v, hasFocus) -> {
|
||||||
@Override
|
|
||||||
public void onFocusChange(View v, boolean hasFocus) {
|
|
||||||
if (hasFocus) {
|
if (hasFocus) {
|
||||||
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
InputMethodManager imm = (InputMethodManager) getActivity()
|
||||||
|
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
if (imm != null) imm.showSoftInput(hexEditText, InputMethodManager.SHOW_IMPLICIT);
|
if (imm != null) imm.showSoftInput(hexEditText, InputMethodManager.SHOW_IMPLICIT);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return contentView;
|
return contentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override public boolean onTouch( View v, MotionEvent event) {
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
if (v != hexEditText && hexEditText.hasFocus()) {
|
if (v != hexEditText && hexEditText.hasFocus()) {
|
||||||
hexEditText.clearFocus();
|
hexEditText.clearFocus();
|
||||||
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
InputMethodManager imm = (InputMethodManager) getActivity()
|
||||||
|
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
if (imm != null) imm.hideSoftInputFromWindow(hexEditText.getWindowToken(), 0);
|
if (imm != null) imm.hideSoftInputFromWindow(hexEditText.getWindowToken(), 0);
|
||||||
hexEditText.clearFocus();
|
hexEditText.clearFocus();
|
||||||
return true;
|
return true;
|
||||||
|
@ -319,13 +339,15 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onColorChanged(int newColor) {
|
@Override
|
||||||
|
public void onColorChanged(int newColor) {
|
||||||
color = newColor;
|
color = newColor;
|
||||||
newColorPanel.setColor(newColor);
|
newColorPanel.setColor(newColor);
|
||||||
if (!fromEditText) {
|
if (!fromEditText) {
|
||||||
setHex(newColor);
|
setHex(newColor);
|
||||||
if (hexEditText.hasFocus()) {
|
if (hexEditText.hasFocus()) {
|
||||||
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
InputMethodManager imm = (InputMethodManager) getActivity()
|
||||||
|
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
if (imm != null) imm.hideSoftInputFromWindow(hexEditText.getWindowToken(), 0);
|
if (imm != null) imm.hideSoftInputFromWindow(hexEditText.getWindowToken(), 0);
|
||||||
hexEditText.clearFocus();
|
hexEditText.clearFocus();
|
||||||
}
|
}
|
||||||
|
@ -333,15 +355,18 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
fromEditText = false;
|
fromEditText = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void afterTextChanged(Editable s) {
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
if (hexEditText.isFocused()) {
|
if (hexEditText.isFocused()) {
|
||||||
try {
|
try {
|
||||||
int color = parseColorString(s.toString());
|
int color = parseColorString(s.toString());
|
||||||
|
@ -437,8 +462,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
contentView.findViewById(R.id.shades_divider).setVisibility(View.GONE);
|
contentView.findViewById(R.id.shades_divider).setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter = new ColorPaletteAdapter(new ColorPaletteAdapter.OnColorSelectedListener() {
|
adapter = new ColorPaletteAdapter(newColor -> {
|
||||||
@Override public void onColorSelected(int newColor) {
|
|
||||||
if (color == newColor) {
|
if (color == newColor) {
|
||||||
colorPickerDialogListener.onColorSelected(dialogId, color);
|
colorPickerDialogListener.onColorSelected(dialogId, color);
|
||||||
dismiss();
|
dismiss();
|
||||||
|
@ -448,7 +472,6 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
if (showColorShades) {
|
if (showColorShades) {
|
||||||
createColorShades(color);
|
createColorShades(color);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, presets, getSelectedItemPosition(), colorShape);
|
}, presets, getSelectedItemPosition(), colorShape);
|
||||||
|
|
||||||
gridView.setAdapter(adapter);
|
gridView.setAdapter(adapter);
|
||||||
|
@ -468,7 +491,8 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
presets = getArguments().getIntArray(ARG_PRESETS);
|
presets = getArguments().getIntArray(ARG_PRESETS);
|
||||||
if (presets == null) presets = MATERIAL_COLORS;
|
if (presets == null) presets = MATERIAL_COLORS;
|
||||||
boolean isMaterialColors = presets == MATERIAL_COLORS;
|
boolean isMaterialColors = presets == MATERIAL_COLORS;
|
||||||
presets = Arrays.copyOf(presets, presets.length); // don't update the original array when modifying alpha
|
presets = Arrays.copyOf(presets, presets.length);
|
||||||
|
// don't update the original array when modifying alpha
|
||||||
if (alpha != 255) {
|
if (alpha != 255) {
|
||||||
// add alpha to the presets
|
// add alpha to the presets
|
||||||
for (int i = 0; i < presets.length; i++) {
|
for (int i = 0; i < presets.length; i++) {
|
||||||
|
@ -501,7 +525,8 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int horizontalPadding = getResources().getDimensionPixelSize(R.dimen.cpv_item_horizontal_padding);
|
final int horizontalPadding = getResources()
|
||||||
|
.getDimensionPixelSize(R.dimen.cpv_item_horizontal_padding);
|
||||||
|
|
||||||
for (final int colorShade : colorShades) {
|
for (final int colorShade : colorShades) {
|
||||||
int layoutResId;
|
int layoutResId;
|
||||||
|
@ -514,21 +539,19 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
final View view = View.inflate(getActivity(), layoutResId, null);
|
final View view = View.inflate(getActivity(), layoutResId, null);
|
||||||
final ColorPanelView colorPanelView = view.findViewById(R.id.cpv_color_panel_view);
|
final ColorPanelView colorPanelView = view.findViewById(R.id.cpv_color_panel_view);
|
||||||
|
|
||||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) colorPanelView.getLayoutParams();
|
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) colorPanelView
|
||||||
|
.getLayoutParams();
|
||||||
params.leftMargin = params.rightMargin = horizontalPadding;
|
params.leftMargin = params.rightMargin = horizontalPadding;
|
||||||
colorPanelView.setLayoutParams(params);
|
colorPanelView.setLayoutParams(params);
|
||||||
colorPanelView.setColor(colorShade);
|
colorPanelView.setColor(colorShade);
|
||||||
shadesLayout.addView(view);
|
shadesLayout.addView(view);
|
||||||
|
|
||||||
colorPanelView.post(new Runnable() {
|
colorPanelView.post(() -> {
|
||||||
@Override public void run() {
|
|
||||||
// The color is black when rotating the dialog. This is a dirty fix. WTF!?
|
// The color is black when rotating the dialog. This is a dirty fix. WTF!?
|
||||||
colorPanelView.setColor(colorShade);
|
colorPanelView.setColor(colorShade);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
colorPanelView.setOnClickListener(new View.OnClickListener() {
|
colorPanelView.setOnClickListener(v -> {
|
||||||
@Override public void onClick(View v) {
|
|
||||||
if (v.getTag() instanceof Boolean && (Boolean) v.getTag()) {
|
if (v.getTag() instanceof Boolean && (Boolean) v.getTag()) {
|
||||||
colorPickerDialogListener.onColorSelected(dialogId, ColorPickerDialog.this.color);
|
colorPickerDialogListener.onColorSelected(dialogId, ColorPickerDialog.this.color);
|
||||||
dismiss();
|
dismiss();
|
||||||
|
@ -549,13 +572,10 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
}
|
}
|
||||||
cpv.setTag(cpv == v);
|
cpv.setTag(cpv == v);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
colorPanelView.setOnLongClickListener(new View.OnLongClickListener() {
|
colorPanelView.setOnLongClickListener(v -> {
|
||||||
@Override public boolean onLongClick(View v) {
|
|
||||||
colorPanelView.showHint();
|
colorPanelView.showHint();
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,7 +619,8 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
int percentage = (int) ((double) progress * 100 / 255);
|
int percentage = (int) ((double) progress * 100 / 255);
|
||||||
transparencyPercText.setText(String.format(Locale.ENGLISH, "%d%%", percentage));
|
transparencyPercText.setText(String.format(Locale.ENGLISH, "%d%%", percentage));
|
||||||
transparencySeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
transparencySeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
int percentage = (int) ((double) progress * 100 / 255);
|
int percentage = (int) ((double) progress * 100 / 255);
|
||||||
transparencyPercText.setText(String.format(Locale.ENGLISH, "%d%%", percentage));
|
transparencyPercText.setText(String.format(Locale.ENGLISH, "%d%%", percentage));
|
||||||
int alpha = 255 - progress;
|
int alpha = 255 - progress;
|
||||||
|
@ -649,11 +670,13 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
color = Color.argb(alpha, red, green, blue);
|
color = Color.argb(alpha, red, green, blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onStartTrackingTouch(SeekBar seekBar) {
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onStopTrackingTouch(SeekBar seekBar) {
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -667,14 +690,14 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!present) {
|
if (present) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
int[] newArray = new int[array.length + 1];
|
int[] newArray = new int[array.length + 1];
|
||||||
newArray[0] = value;
|
newArray[0] = value;
|
||||||
System.arraycopy(array, 0, newArray, 1, newArray.length - 1);
|
System.arraycopy(array, 0, newArray, 1, newArray.length - 1);
|
||||||
return newArray;
|
return newArray;
|
||||||
}
|
}
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int[] pushIfNotExists(int[] array, int value) {
|
private int[] pushIfNotExists(int[] array, int value) {
|
||||||
boolean present = false;
|
boolean present = false;
|
||||||
|
@ -706,18 +729,23 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
|
|
||||||
// region Builder
|
// region Builder
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess") public static final class Builder {
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
@StringRes int dialogTitle = R.string.cpv_default_title;
|
@StringRes
|
||||||
@DialogType int dialogType = TYPE_PRESETS;
|
int dialogTitle = R.string.cpv_default_title;
|
||||||
|
@DialogType
|
||||||
|
int dialogType = TYPE_PRESETS;
|
||||||
int[] presets = MATERIAL_COLORS;
|
int[] presets = MATERIAL_COLORS;
|
||||||
@ColorInt int color = Color.BLACK;
|
@ColorInt
|
||||||
|
int color = Color.BLACK;
|
||||||
int dialogId = 0;
|
int dialogId = 0;
|
||||||
boolean showAlphaSlider = false;
|
boolean showAlphaSlider = false;
|
||||||
boolean allowPresets = true;
|
boolean allowPresets = true;
|
||||||
boolean allowCustom = true;
|
boolean allowCustom = true;
|
||||||
boolean showColorShades = true;
|
boolean showColorShades = true;
|
||||||
@ColorShape int colorShape = ColorShape.CIRCLE;
|
@ColorShape
|
||||||
|
int colorShape = ColorShape.CIRCLE;
|
||||||
|
|
||||||
/*package*/ Builder() {
|
/*package*/ Builder() {
|
||||||
|
|
||||||
|
@ -726,8 +754,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set the dialog title string resource id
|
* Set the dialog title string resource id
|
||||||
*
|
*
|
||||||
* @param dialogTitle
|
* @param dialogTitle The string resource used for the dialog title
|
||||||
* The string resource used for the dialog title
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setDialogTitle(@StringRes int dialogTitle) {
|
public Builder setDialogTitle(@StringRes int dialogTitle) {
|
||||||
|
@ -738,8 +765,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set which dialog view to show.
|
* Set which dialog view to show.
|
||||||
*
|
*
|
||||||
* @param dialogType
|
* @param dialogType Either {@link ColorPickerDialog#TYPE_CUSTOM} or {@link ColorPickerDialog#TYPE_PRESETS}.
|
||||||
* Either {@link ColorPickerDialog#TYPE_CUSTOM} or {@link ColorPickerDialog#TYPE_PRESETS}.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setDialogType(@DialogType int dialogType) {
|
public Builder setDialogType(@DialogType int dialogType) {
|
||||||
|
@ -750,8 +776,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set the colors used for the presets
|
* Set the colors used for the presets
|
||||||
*
|
*
|
||||||
* @param presets
|
* @param presets An array of color ints.
|
||||||
* An array of color ints.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setPresets(@NonNull int[] presets) {
|
public Builder setPresets(@NonNull int[] presets) {
|
||||||
|
@ -762,8 +787,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set the original color
|
* Set the original color
|
||||||
*
|
*
|
||||||
* @param color
|
* @param color The default color for the color picker
|
||||||
* The default color for the color picker
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setColor(int color) {
|
public Builder setColor(int color) {
|
||||||
|
@ -774,8 +798,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set the dialog id used for callbacks
|
* Set the dialog id used for callbacks
|
||||||
*
|
*
|
||||||
* @param dialogId
|
* @param dialogId The id that is sent back to the {@link ColorPickerDialogListener}.
|
||||||
* The id that is sent back to the {@link ColorPickerDialogListener}.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setDialogId(int dialogId) {
|
public Builder setDialogId(int dialogId) {
|
||||||
|
@ -786,8 +809,8 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Show the alpha slider
|
* Show the alpha slider
|
||||||
*
|
*
|
||||||
* @param showAlphaSlider
|
* @param showAlphaSlider {@code true} to show the alpha slider. Currently only supported with
|
||||||
* {@code true} to show the alpha slider. Currently only supported with the {@link ColorPickerView}.
|
* the {@link ColorPickerView}.
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setShowAlphaSlider(boolean showAlphaSlider) {
|
public Builder setShowAlphaSlider(boolean showAlphaSlider) {
|
||||||
|
@ -798,8 +821,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Show/Hide a neutral button to select preset colors.
|
* Show/Hide a neutral button to select preset colors.
|
||||||
*
|
*
|
||||||
* @param allowPresets
|
* @param allowPresets {@code false} to disable showing the presets button.
|
||||||
* {@code false} to disable showing the presets button.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setAllowPresets(boolean allowPresets) {
|
public Builder setAllowPresets(boolean allowPresets) {
|
||||||
|
@ -810,8 +832,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Show/Hide the neutral button to select a custom color.
|
* Show/Hide the neutral button to select a custom color.
|
||||||
*
|
*
|
||||||
* @param allowCustom
|
* @param allowCustom {@code false} to disable showing the custom button.
|
||||||
* {@code false} to disable showing the custom button.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setAllowCustom(boolean allowCustom) {
|
public Builder setAllowCustom(boolean allowCustom) {
|
||||||
|
@ -822,8 +843,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Show/Hide the color shades in the presets picker
|
* Show/Hide the color shades in the presets picker
|
||||||
*
|
*
|
||||||
* @param showColorShades
|
* @param showColorShades {@code false} to hide the color shades.
|
||||||
* {@code false} to hide the color shades.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setShowColorShades(boolean showColorShades) {
|
public Builder setShowColorShades(boolean showColorShades) {
|
||||||
|
@ -834,8 +854,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Set the shape of the color panel view.
|
* Set the shape of the color panel view.
|
||||||
*
|
*
|
||||||
* @param colorShape
|
* @param colorShape Either {@link ColorShape#CIRCLE} or {@link ColorShape#SQUARE}.
|
||||||
* Either {@link ColorShape#CIRCLE} or {@link ColorShape#SQUARE}.
|
|
||||||
* @return This builder object for chaining method calls
|
* @return This builder object for chaining method calls
|
||||||
*/
|
*/
|
||||||
public Builder setColorShape(int colorShape) {
|
public Builder setColorShape(int colorShape) {
|
||||||
|
@ -847,7 +866,7 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
* Create the {@link ColorPickerDialog} instance.
|
* Create the {@link ColorPickerDialog} instance.
|
||||||
*
|
*
|
||||||
* @return A new {@link ColorPickerDialog}.
|
* @return A new {@link ColorPickerDialog}.
|
||||||
* @see #show(Activity)
|
* @see #show(FragmentActivity)
|
||||||
*/
|
*/
|
||||||
public ColorPickerDialog create() {
|
public ColorPickerDialog create() {
|
||||||
ColorPickerDialog dialog = new ColorPickerDialog();
|
ColorPickerDialog dialog = new ColorPickerDialog();
|
||||||
|
@ -869,13 +888,11 @@ public class ColorPickerDialog extends DialogFragment implements OnTouchListener
|
||||||
/**
|
/**
|
||||||
* Create and show the {@link ColorPickerDialog} created with this builder.
|
* Create and show the {@link ColorPickerDialog} created with this builder.
|
||||||
*
|
*
|
||||||
* @param activity
|
* @param activity The current activity.
|
||||||
* The current activity.
|
|
||||||
*/
|
*/
|
||||||
public void show(Activity activity) {
|
public void show(FragmentActivity activity) {
|
||||||
create().show(activity.getFragmentManager(), "color-picker-dialog");
|
create().show(activity.getSupportFragmentManager(), "color-picker-dialog");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
|
|
@ -159,7 +159,8 @@ public class ColorPickerView extends View {
|
||||||
init(context, attrs);
|
init(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Parcelable onSaveInstanceState(){
|
@Override
|
||||||
|
public Parcelable onSaveInstanceState() {
|
||||||
Bundle state = new Bundle();
|
Bundle state = new Bundle();
|
||||||
state.putParcelable("instanceState", super.onSaveInstanceState());
|
state.putParcelable("instanceState", super.onSaveInstanceState());
|
||||||
state.putInt("alpha", alpha);
|
state.putInt("alpha", alpha);
|
||||||
|
@ -172,7 +173,8 @@ public class ColorPickerView extends View {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onRestoreInstanceState( Parcelable state ){
|
@Override
|
||||||
|
public void onRestoreInstanceState(Parcelable state) {
|
||||||
|
|
||||||
if (state instanceof Bundle) {
|
if (state instanceof Bundle) {
|
||||||
Bundle bundle = (Bundle) state;
|
Bundle bundle = (Bundle) state;
|
||||||
|
@ -262,7 +264,8 @@ public class ColorPickerView extends View {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onDraw( Canvas canvas ){
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
if (drawingRect.width() <= 0 || drawingRect.height() <= 0) {
|
if (drawingRect.width() <= 0 || drawingRect.height() <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +555,8 @@ public class ColorPickerView extends View {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override public boolean onTouchEvent( MotionEvent event ){
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.getParent().requestDisallowInterceptTouchEvent(true);
|
this.getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
|
@ -617,7 +621,8 @@ public class ColorPickerView extends View {
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec ){
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
int finalWidth;
|
int finalWidth;
|
||||||
int finalHeight;
|
int finalHeight;
|
||||||
|
|
||||||
|
@ -639,12 +644,8 @@ public class ColorPickerView extends View {
|
||||||
h += panelSpacingPx + alphaPanelHeightPx;
|
h += panelSpacingPx + alphaPanelHeightPx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( h > heightAllowed ){
|
|
||||||
//We can't fit the view in this container, set the size to whatever was allowed.
|
//We can't fit the view in this container, set the size to whatever was allowed.
|
||||||
finalHeight = heightAllowed;
|
finalHeight = Math.min(h, heightAllowed);
|
||||||
}else{
|
|
||||||
finalHeight = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
finalWidth = widthAllowed;
|
finalWidth = widthAllowed;
|
||||||
|
|
||||||
|
@ -657,12 +658,8 @@ public class ColorPickerView extends View {
|
||||||
w -= (panelSpacingPx + alphaPanelHeightPx);
|
w -= (panelSpacingPx + alphaPanelHeightPx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( w > widthAllowed ){
|
|
||||||
//we can't fit within this container, set the size to whatever was allowed.
|
//we can't fit within this container, set the size to whatever was allowed.
|
||||||
finalWidth = widthAllowed;
|
finalWidth = Math.min(w, widthAllowed);
|
||||||
}else{
|
|
||||||
finalWidth = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
finalHeight = heightAllowed;
|
finalHeight = heightAllowed;
|
||||||
|
|
||||||
|
@ -722,39 +719,28 @@ public class ColorPickerView extends View {
|
||||||
finalHeight + getPaddingTop() + getPaddingBottom());
|
finalHeight + getPaddingTop() + getPaddingBottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
// private int getPreferredWidth() {
|
@Override
|
||||||
// //Our preferred width and height is 200dp for the square sat / val rectangle.
|
public int getPaddingTop() {
|
||||||
// int width = DrawingUtils.dpToPx(getContext(), 200);
|
|
||||||
//
|
|
||||||
// return (width + huePanelWidthPx + panelSpacingPx);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private int getPreferredHeight() {
|
|
||||||
// int height = DrawingUtils.dpToPx(getContext(), 200);
|
|
||||||
//
|
|
||||||
// if (showAlphaPanel) {
|
|
||||||
// height += panelSpacingPx + alphaPanelHeightPx;
|
|
||||||
// }
|
|
||||||
// return height;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override public int getPaddingTop(){
|
|
||||||
return Math.max(super.getPaddingTop(), mRequiredPadding);
|
return Math.max(super.getPaddingTop(), mRequiredPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getPaddingBottom(){
|
@Override
|
||||||
|
public int getPaddingBottom() {
|
||||||
return Math.max(super.getPaddingBottom(), mRequiredPadding);
|
return Math.max(super.getPaddingBottom(), mRequiredPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getPaddingLeft(){
|
@Override
|
||||||
|
public int getPaddingLeft() {
|
||||||
return Math.max(super.getPaddingLeft(), mRequiredPadding);
|
return Math.max(super.getPaddingLeft(), mRequiredPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getPaddingRight(){
|
@Override
|
||||||
|
public int getPaddingRight() {
|
||||||
return Math.max(super.getPaddingRight(), mRequiredPadding);
|
return Math.max(super.getPaddingRight(), mRequiredPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onSizeChanged( int w, int h, int oldw, int oldh ){
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
|
||||||
drawingRect = new Rect();
|
drawingRect = new Rect();
|
||||||
|
@ -983,15 +969,13 @@ public class ColorPickerView extends View {
|
||||||
return alphaSliderText;
|
return alphaSliderText;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BitmapCache {
|
private static class BitmapCache {
|
||||||
|
|
||||||
public Canvas canvas;
|
public Canvas canvas;
|
||||||
public Bitmap bitmap;
|
public Bitmap bitmap;
|
||||||
public float value;
|
public float value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnColorChangedListener {
|
public interface OnColorChangedListener {
|
||||||
|
|
||||||
void onColorChanged(int newColor);
|
void onColorChanged(int newColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,17 +16,21 @@
|
||||||
|
|
||||||
package com.jrummyapps.android.colorpicker;
|
package com.jrummyapps.android.colorpicker;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import androidx.annotation.ColorInt;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.jrummyapps.android.colorpicker.ColorPickerDialog.DialogType;
|
import com.jrummyapps.android.colorpicker.ColorPickerDialog.DialogType;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Preference to select a color
|
* A Preference to select a color
|
||||||
*/
|
*/
|
||||||
|
@ -89,7 +93,8 @@ public class ColorPreference extends Preference implements ColorPickerDialogList
|
||||||
a.recycle();
|
a.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onClick() {
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
super.onClick();
|
super.onClick();
|
||||||
if (onShowDialogListener != null) {
|
if (onShowDialogListener != null) {
|
||||||
onShowDialogListener.onShowColorPickerDialog((String) getTitle(), color);
|
onShowDialogListener.onShowColorPickerDialog((String) getTitle(), color);
|
||||||
|
@ -106,18 +111,28 @@ public class ColorPreference extends Preference implements ColorPickerDialogList
|
||||||
.setColor(color)
|
.setColor(color)
|
||||||
.create();
|
.create();
|
||||||
dialog.setColorPickerDialogListener(ColorPreference.this);
|
dialog.setColorPickerDialogListener(ColorPreference.this);
|
||||||
Activity activity = (Activity) getContext();
|
FragmentManager fm = getFragmentManager();
|
||||||
dialog.show(activity.getFragmentManager(), getFragmentTag());
|
if (fm != null) {
|
||||||
|
dialog.show(fm, getFragmentTag());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onAttachedToActivity() {
|
@Nullable
|
||||||
|
private FragmentManager getFragmentManager() {
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof FragmentActivity) {
|
||||||
|
return ((FragmentActivity) context).getSupportFragmentManager();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAttachedToActivity() {
|
||||||
super.onAttachedToActivity();
|
super.onAttachedToActivity();
|
||||||
|
FragmentManager fm = getFragmentManager();
|
||||||
if (showDialog) {
|
if (showDialog && fm != null) {
|
||||||
Activity activity = (Activity) getContext();
|
ColorPickerDialog fragment = (ColorPickerDialog) fm.findFragmentByTag(getFragmentTag());
|
||||||
ColorPickerDialog fragment =
|
|
||||||
(ColorPickerDialog) activity.getFragmentManager().findFragmentByTag(getFragmentTag());
|
|
||||||
if (fragment != null) {
|
if (fragment != null) {
|
||||||
// re-bind preference to fragment
|
// re-bind preference to fragment
|
||||||
fragment.setColorPickerDialogListener(this);
|
fragment.setColorPickerDialogListener(this);
|
||||||
|
@ -125,15 +140,17 @@ public class ColorPreference extends Preference implements ColorPickerDialogList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onBindView(View view) {
|
@Override
|
||||||
|
protected void onBindView(View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
ColorPanelView preview = (ColorPanelView) view.findViewById(R.id.cpv_preference_preview_color_panel);
|
ColorPanelView preview = view.findViewById(R.id.cpv_preference_preview_color_panel);
|
||||||
if (preview != null) {
|
if (preview != null) {
|
||||||
preview.setColor(color);
|
preview.setColor(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
|
@Override
|
||||||
|
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
|
||||||
if (restorePersistedValue) {
|
if (restorePersistedValue) {
|
||||||
color = getPersistedInt(0xFF000000);
|
color = getPersistedInt(0xFF000000);
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,23 +159,25 @@ public class ColorPreference extends Preference implements ColorPickerDialogList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected Object onGetDefaultValue(TypedArray a, int index) {
|
@Override
|
||||||
|
protected Object onGetDefaultValue(TypedArray a, int index) {
|
||||||
return a.getInteger(index, Color.BLACK);
|
return a.getInteger(index, Color.BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onColorSelected(int dialogId, @ColorInt int color) {
|
@Override
|
||||||
|
public void onColorSelected(int dialogId, @ColorInt int color) {
|
||||||
saveValue(color);
|
saveValue(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onDialogDismissed(int dialogId) {
|
@Override
|
||||||
|
public void onDialogDismissed(int dialogId) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the new color
|
* Set the new color
|
||||||
*
|
*
|
||||||
* @param color
|
* @param color The newly selected color
|
||||||
* The newly selected color
|
|
||||||
*/
|
*/
|
||||||
public void saveValue(@ColorInt int color) {
|
public void saveValue(@ColorInt int color) {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
|
@ -190,8 +209,7 @@ public class ColorPreference extends Preference implements ColorPickerDialogList
|
||||||
* Call {@link #saveValue(int)} after the user chooses a color.
|
* Call {@link #saveValue(int)} after the user chooses a color.
|
||||||
* If this is set then it is up to you to show the dialog.
|
* If this is set then it is up to you to show the dialog.
|
||||||
*
|
*
|
||||||
* @param listener
|
* @param listener The listener to show the dialog
|
||||||
* The listener to show the dialog
|
|
||||||
*/
|
*/
|
||||||
public void setOnShowDialogListener(OnShowDialogListener listener) {
|
public void setOnShowDialogListener(OnShowDialogListener listener) {
|
||||||
onShowDialogListener = listener;
|
onShowDialogListener = listener;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#Wed May 05 20:20:56 JST 2021
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
@ -44,10 +44,9 @@ dependencies {
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
|
||||||
|
|
||||||
testImplementation "junit:junit:$junit_version"
|
testImplementation "junit:junit:$junit_version"
|
||||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines_version"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="jp.juggler.apng.sample"
|
package="jp.juggler.apng.sample">
|
||||||
>
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission
|
||||||
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
tools:ignore="ScopedStorage" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:fullBackupOnly="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme">
|
||||||
>
|
|
||||||
|
|
||||||
<activity android:name=".ActList">
|
<activity
|
||||||
|
android:name=".ActList"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
|
|
@ -78,21 +78,12 @@ class ActList : AppCompatActivity(), CoroutineScope {
|
||||||
permissions: Array<String>,
|
permissions: Array<String>,
|
||||||
grantResults: IntArray
|
grantResults: IntArray
|
||||||
) {
|
) {
|
||||||
when (requestCode) {
|
if( requestCode == PERMISSION_REQUEST_CODE_STORAGE){
|
||||||
PERMISSION_REQUEST_CODE_STORAGE -> {
|
if (grantResults.all{ it == PackageManager.PERMISSION_GRANTED }) {
|
||||||
// If request is cancelled, the result arrays are empty.
|
// 特に何もしてないらしい
|
||||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
// permission was granted, yay! Do the
|
|
||||||
// contacts-related task you need to do.
|
|
||||||
} else {
|
|
||||||
// permission denied, boo! Disable the
|
|
||||||
// functionality that depends on this permission.
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
// other 'case' lines to check for other
|
|
||||||
// permissions this app might request
|
|
||||||
}
|
}
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun load() = launch {
|
private fun load() = launch {
|
||||||
|
|
|
@ -117,7 +117,7 @@ class ActViewer : AppCompatActivity() , CoroutineScope {
|
||||||
|
|
||||||
dir.mkdirs()
|
dir.mkdirs()
|
||||||
if(! dir.exists() ) {
|
if(! dir.exists() ) {
|
||||||
Log.e(TAG, "Directory not exists: ${dir}")
|
Log.e(TAG, "Directory not exists: $dir")
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
val frames = apngFrames.frames
|
val frames = apngFrames.frames
|
||||||
|
@ -127,7 +127,7 @@ class ActViewer : AppCompatActivity() , CoroutineScope {
|
||||||
}
|
}
|
||||||
var i=0
|
var i=0
|
||||||
for( f in frames) {
|
for( f in frames) {
|
||||||
Log.d(TAG, "${title}[${i}] timeWidth=${f.timeWidth}")
|
Log.d(TAG, "$title[$i] timeWidth=${f.timeWidth}")
|
||||||
val bitmap = f.bitmap
|
val bitmap = f.bitmap
|
||||||
|
|
||||||
FileOutputStream( File(dir,"${title}_${i}.png")).use{ fo ->
|
FileOutputStream( File(dir,"${title}_${i}.png")).use{ fo ->
|
||||||
|
|
Loading…
Reference in New Issue