Refactor: SDK 28, androidx, ... (#221)
This commit is contained in:
parent
b95ff6d63a
commit
a6baee2ca2
157 changed files with 1093 additions and 1134 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,7 +5,6 @@ build
|
||||||
bin
|
bin
|
||||||
gen
|
gen
|
||||||
project.properties
|
project.properties
|
||||||
gradle.properties
|
|
||||||
local.properties
|
local.properties
|
||||||
*iml
|
*iml
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'spoon'
|
apply plugin: 'com.jaredsburrows.spoon'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
apply plugin: 'kotlin-android-extensions'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
|
@ -10,20 +10,21 @@ apply plugin: 'com.github.triplet.play'
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
|
google()
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
maven { url 'https://maven.google.com' }
|
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } // For Spoon snapshot, until 2.0.0 is released
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
||||||
compileSdkVersion 25
|
compileSdkVersion 28
|
||||||
buildToolsVersion "25.0.3"
|
buildToolsVersion "28.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode 349
|
versionCode 349
|
||||||
versionName "3.4.9"
|
versionName "3.4.9"
|
||||||
minSdkVersion 9
|
minSdkVersion 14
|
||||||
targetSdkVersion 25
|
targetSdkVersion 28
|
||||||
applicationId "org.ligi.passandroid"
|
applicationId "org.ligi.passandroid"
|
||||||
testInstrumentationRunner "org.ligi.passandroid.AppReplacingRunner"
|
testInstrumentationRunner "org.ligi.passandroid.AppReplacingRunner"
|
||||||
archivesBaseName = "PassAndroid-$versionName"
|
archivesBaseName = "PassAndroid-$versionName"
|
||||||
|
@ -62,6 +63,14 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hacky workaround to add spoon task that executes all variants
|
||||||
|
task spoon {
|
||||||
|
dependsOn {
|
||||||
|
tasks.findAll { task -> task.name != 'spoon' && task.name.startsWith('spoon') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
android.variantFilter { variant ->
|
android.variantFilter { variant ->
|
||||||
def maps = variant.getFlavors().get(0).name
|
def maps = variant.getFlavors().get(0).name
|
||||||
def analytics = variant.getFlavors().get(1).name
|
def analytics = variant.getFlavors().get(1).name
|
||||||
|
@ -85,7 +94,6 @@ android {
|
||||||
|
|
||||||
exclude 'META-INF/maven/com.google.guava/guava/pom.properties'
|
exclude 'META-INF/maven/com.google.guava/guava/pom.properties'
|
||||||
exclude 'META-INF/maven/com.google.guava/guava/pom.xml'
|
exclude 'META-INF/maven/com.google.guava/guava/pom.xml'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
|
@ -100,97 +108,94 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
configurations {
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
|
}
|
||||||
// http://stackoverflow.com/questions/30578243/why-would-adding-espresso-contrib-cause-an-inflateexception
|
|
||||||
androidTestCompile.exclude group: 'com.android.support', module: 'appcompat-v7'
|
|
||||||
androidTestCompile.exclude group: 'com.android.support', module: 'design'
|
|
||||||
androidTestCompile.exclude group: 'com.android.support', module: 'support-v4'
|
|
||||||
androidTestCompile.exclude group: 'com.android.support', module: 'support-annotations'
|
|
||||||
androidTestCompile.exclude group: 'com.android.support', module: 'preference-v7'
|
|
||||||
androidTestCompile.exclude module: 'recyclerview-v7'
|
|
||||||
androidTestCompile.exclude module: 'kotlin-stdlib'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.github.hotchemi:permissionsdispatcher:2.3.2'
|
implementation 'org.permissionsdispatcher:permissionsdispatcher:4.3.0'
|
||||||
kapt 'com.github.hotchemi:permissionsdispatcher-processor:2.3.2'
|
kapt 'org.permissionsdispatcher:permissionsdispatcher-processor:4.3.0'
|
||||||
|
|
||||||
compile 'com.github.salomonbrys.kodein:kodein:4.1.0'
|
implementation 'com.github.salomonbrys.kodein:kodein:4.1.0'
|
||||||
|
compileOnly 'org.glassfish:javax.annotation:3.1.1'
|
||||||
|
|
||||||
provided 'org.glassfish:javax.annotation:10.0-b28'
|
// spoon snapshot, until 2.0.0 is released
|
||||||
|
androidTestImplementation 'com.squareup.spoon:spoon-client:2.0.0-SNAPSHOT'
|
||||||
|
androidTestImplementation 'com.github.ligi:trulesk:0.28'
|
||||||
|
androidTestImplementation 'androidx.test:core:1.1.0'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.1'
|
||||||
|
androidTestImplementation 'com.squareup.assertj:assertj-android:1.2.0'
|
||||||
|
androidTestImplementation "org.mockito:mockito-core:$mockito_version"
|
||||||
|
androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.21.0'
|
||||||
|
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
androidTestImplementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
|
androidTestImplementation 'com.google.android.material:material:1.0.0'
|
||||||
|
|
||||||
androidTestCompile 'com.github.ligi:trulesk:0.21'
|
implementation 'com.github.ligi:TouchImageView:2.1'
|
||||||
|
implementation 'com.github.ligi:ExtraCompats:0.5'
|
||||||
|
implementation 'net.lingala.zip4j:zip4j:1.3.2'
|
||||||
|
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.0'
|
||||||
|
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
|
||||||
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.1'
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
|
implementation 'androidx.preference:preference:1.0.0'
|
||||||
|
implementation 'androidx.annotation:annotation:1.0.2'
|
||||||
|
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
||||||
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
|
implementation 'net.i2p.android.ext:floatingactionbutton:1.10.1'
|
||||||
|
|
||||||
androidTestCompile 'com.squareup.assertj:assertj-android:1.1.1'
|
implementation 'com.github.ligi:KAXT:0.22'
|
||||||
|
implementation 'com.github.ligi:KAXTUI:0.8'
|
||||||
|
implementation 'com.github.ligi:loadtoast:1.10.11'
|
||||||
|
implementation 'com.github.ligi:tracedroid:2.1'
|
||||||
|
|
||||||
androidTestCompile "org.mockito:mockito-core:$mockito_version"
|
forPlayImplementation 'com.github.ligi.snackengage:snackengage-playrate:0.18'
|
||||||
androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0'
|
forFDroidImplementation 'com.github.ligi.snackengage:snackengage-playrate:0.18'
|
||||||
|
forAmazonImplementation 'com.github.ligi.snackengage:snackengage-amazonrate:0.18'
|
||||||
|
|
||||||
androidTestCompile 'com.google.code.findbugs:jsr305:3.0.2'
|
// https://medium.com/square-corner-blog/okhttp-3-13-requires-android-5-818bb78d07ce
|
||||||
|
// Don't update to >=3.13 before minSDK 21 + Java 8
|
||||||
|
//noinspection GradleDependency
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
|
||||||
|
|
||||||
androidTestCompile "com.android.support:appcompat-v7:$support_version"
|
implementation 'com.larswerkman:HoloColorPicker:1.5'
|
||||||
androidTestCompile "com.android.support:design:$support_version"
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
|
||||||
compile 'com.github.ligi:TouchImageView:2.1'
|
// https://github.com/square/moshi/issues/738
|
||||||
compile 'com.github.ligi:ExtraCompats:0.4'
|
// either wait for ProGuard update or use R8 instead (android.enableR8=true)
|
||||||
|
//noinspection GradleDependency
|
||||||
|
implementation 'com.squareup.moshi:moshi:1.7.0'
|
||||||
|
|
||||||
compile 'net.lingala.zip4j:zip4j:1.3.2'
|
implementation 'com.chibatching.kotpref:kotpref:2.6.0'
|
||||||
compile 'com.jakewharton.threetenabp:threetenabp:1.1.0'
|
implementation 'com.chibatching.kotpref:initializer:2.6.0'
|
||||||
compile 'org.greenrobot:eventbus:3.0.0'
|
testImplementation 'androidx.annotation:annotation:1.0.2'
|
||||||
|
testImplementation 'com.squareup.assertj:assertj-android:1.2.0'
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
testImplementation 'junit:junit:4.12'
|
||||||
|
testImplementation "org.mockito:mockito-core:$mockito_version"
|
||||||
compile "com.android.support:support-annotations:$support_version"
|
testImplementation 'org.threeten:threetenbp:1.3.8'
|
||||||
compile "com.android.support:recyclerview-v7:$support_version"
|
|
||||||
compile "com.android.support:appcompat-v7:$support_version"
|
|
||||||
compile "com.android.support:cardview-v7:$support_version"
|
|
||||||
compile "com.android.support:design:$support_version"
|
|
||||||
compile "com.android.support:preference-v7:$support_version"
|
|
||||||
|
|
||||||
compile 'net.i2p.android.ext:floatingactionbutton:1.10.1'
|
|
||||||
|
|
||||||
compile 'com.github.ligi:KAXT:0.20'
|
|
||||||
compile 'com.github.ligi:KAXTUI:0.4'
|
|
||||||
compile 'com.github.ligi:loadtoast:1.10.11'
|
|
||||||
compile 'com.github.ligi:tracedroid:1.4'
|
|
||||||
|
|
||||||
forPlayCompile 'com.github.ligi.snackengage:snackengage-playrate:0.15'
|
|
||||||
forFDroidCompile 'com.github.ligi.snackengage:snackengage-playrate:0.15'
|
|
||||||
forAmazonCompile 'com.github.ligi.snackengage:snackengage-amazonrate:0.15'
|
|
||||||
|
|
||||||
compile 'com.squareup.okhttp3:okhttp:3.11.0'
|
|
||||||
compile 'com.larswerkman:HoloColorPicker:1.5'
|
|
||||||
compile 'com.google.code.findbugs:jsr305:3.0.2'
|
|
||||||
compile 'com.squareup.moshi:moshi:1.4.0'
|
|
||||||
|
|
||||||
compile "com.chibatching.kotpref:kotpref:2.6.0"
|
|
||||||
compile "com.chibatching.kotpref:initializer:2.6.0"
|
|
||||||
|
|
||||||
testCompile "com.android.support:support-annotations:$support_version"
|
|
||||||
testCompile 'com.squareup.assertj:assertj-android:1.1.1'
|
|
||||||
testCompile 'junit:junit:4.12'
|
|
||||||
testCompile "org.mockito:mockito-core:${mockito_version}"
|
|
||||||
testCompile 'org.threeten:threetenbp:1.3.7'
|
|
||||||
|
|
||||||
// https://github.com/ligi/PassAndroid/issues/181
|
// https://github.com/ligi/PassAndroid/issues/181
|
||||||
// Don't update to 3.3.1 before minSDK 19 - or replace zxing
|
// Don't upgrade before minSDK 19 - or replace zxing
|
||||||
compile 'com.google.zxing:core:3.3.0'
|
//noinspection GradleDependency
|
||||||
|
implementation 'com.google.zxing:core:3.3.0'
|
||||||
|
|
||||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
|
||||||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4'
|
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
|
||||||
|
|
||||||
withAnalyticsCompile "com.google.android.gms:play-services-analytics:$play_version"
|
// requires minSDK 16 according to docs, not sure if it causes an issue
|
||||||
withMapsCompile "com.google.android.gms:play-services-maps:$play_version"
|
withAnalyticsImplementation 'com.google.android.gms:play-services-analytics:16.0.8'
|
||||||
|
withMapsImplementation 'com.google.android.gms:play-services-maps:16.1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
spoon {
|
spoon {
|
||||||
debug = true
|
debug = true
|
||||||
grantAllPermissions = true
|
grantAll = true
|
||||||
|
baseOutputDir = "build/spoon"
|
||||||
}
|
}
|
||||||
|
|
||||||
play {
|
play {
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
# If your project uses WebView with JS, uncomment the following
|
# If your project uses WebView with JS, uncomment the following
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
# class:
|
# class:
|
||||||
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
public *;
|
# public *;
|
||||||
}
|
#}
|
||||||
|
|
||||||
# optimize
|
# optimize
|
||||||
-optimizationpasses 2
|
-optimizationpasses 2
|
||||||
|
@ -30,12 +30,6 @@
|
||||||
-dontusemixedcaseclassnames
|
-dontusemixedcaseclassnames
|
||||||
-dontskipnonpubliclibraryclasses
|
-dontskipnonpubliclibraryclasses
|
||||||
|
|
||||||
# AppCompat
|
|
||||||
|
|
||||||
-dontwarn android.support.v7.**
|
|
||||||
-keep class android.support.v7.** { *; }
|
|
||||||
-keep interface android.support.v7.** { *; }
|
|
||||||
|
|
||||||
# Keep line numbers to alleviate debugging stack traces
|
# Keep line numbers to alleviate debugging stack traces
|
||||||
|
|
||||||
-renamesourcefileattribute SourceFile
|
-renamesourcefileattribute SourceFile
|
||||||
|
@ -44,7 +38,6 @@
|
||||||
|
|
||||||
### for api client
|
### for api client
|
||||||
|
|
||||||
|
|
||||||
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
|
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
|
||||||
|
|
||||||
-keepclassmembers class * {
|
-keepclassmembers class * {
|
||||||
|
@ -54,7 +47,6 @@
|
||||||
# Needed by Guava
|
# Needed by Guava
|
||||||
# See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI
|
# See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI
|
||||||
|
|
||||||
|
|
||||||
-dontwarn sun.misc.Unsafe
|
-dontwarn sun.misc.Unsafe
|
||||||
-dontwarn com.google.common.collect.MinMaxPriorityQueue
|
-dontwarn com.google.common.collect.MinMaxPriorityQueue
|
||||||
|
|
||||||
|
@ -72,9 +64,6 @@
|
||||||
-keep class **$$ViewBinder { *; }
|
-keep class **$$ViewBinder { *; }
|
||||||
-keepnames class * { @butterknife.Bind *;}
|
-keepnames class * { @butterknife.Bind *;}
|
||||||
|
|
||||||
#### for support 22
|
|
||||||
-dontwarn android.support.**
|
|
||||||
|
|
||||||
#### for guava
|
#### for guava
|
||||||
-dontwarn javax.annotation.**
|
-dontwarn javax.annotation.**
|
||||||
-dontwarn javax.inject.**
|
-dontwarn javax.inject.**
|
||||||
|
@ -105,23 +94,20 @@
|
||||||
-dontwarn java.nio.file.OpenOption
|
-dontwarn java.nio.file.OpenOption
|
||||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||||
|
|
||||||
-keep public class com.google.android.gms.**
|
|
||||||
-dontwarn com.google.android.gms.**
|
|
||||||
|
|
||||||
|
|
||||||
## New rules for EventBus 3.0.x ##
|
## New rules for EventBus 3.0.x ##
|
||||||
# http://greenrobot.org/eventbus/documentation/proguard/
|
# http://greenrobot.org/eventbus/documentation/proguard/
|
||||||
|
|
||||||
-keepattributes *Annotation*
|
-keepattributes *Annotation*
|
||||||
-keepclassmembers class ** {
|
-keepclassmembers class * {
|
||||||
@org.greenrobot.eventbus.Subscribe <methods>;
|
@org.greenrobot.eventbus.Subscribe <methods>;
|
||||||
}
|
}
|
||||||
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
|
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
|
||||||
|
|
||||||
# Only required if you use AsyncExecutor
|
# Only required if you use AsyncExecutor
|
||||||
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
|
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
|
||||||
<init>(java.lang.Throwable);
|
<init>(java.lang.Throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
### for moshi
|
### for moshi
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"message":"",
|
"message":"",
|
||||||
"transfer":"barcode_QR",
|
"transfer":"barcode_QR",
|
||||||
"alternative": {
|
"alternative": {
|
||||||
"order":1,
|
"order":1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,6 @@ class TestApp : App() {
|
||||||
fixedPassListPassStore().setList(emptyList())
|
fixedPassListPassStore().setList(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fixedPassListPassStore() = passStore() as FixedPassListPassStore
|
private fun fixedPassListPassStore() = passStore() as FixedPassListPassStore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,14 @@ package org.ligi.passandroid
|
||||||
import android.app.Activity.RESULT_CANCELED
|
import android.app.Activity.RESULT_CANCELED
|
||||||
import android.app.Instrumentation
|
import android.app.Instrumentation
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.intent.Intents.intended
|
import androidx.test.espresso.intent.Intents.intended
|
||||||
import android.support.test.espresso.intent.Intents.intending
|
import androidx.test.espresso.intent.Intents.intending
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra
|
import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.hasType
|
import androidx.test.espresso.intent.matcher.IntentMatchers.hasType
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.hamcrest.CoreMatchers.not
|
import org.hamcrest.CoreMatchers.not
|
||||||
import org.hamcrest.Matchers.allOf
|
import org.hamcrest.Matchers.allOf
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -23,8 +23,8 @@ import org.threeten.bp.ZonedDateTime
|
||||||
|
|
||||||
class TheAddToCalendar {
|
class TheAddToCalendar {
|
||||||
|
|
||||||
val time = ZonedDateTime.now()
|
private val time = ZonedDateTime.now()
|
||||||
val time2 = ZonedDateTime.now().plusHours(3)
|
private val time2 = ZonedDateTime.now().plusHours(3)
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var rule = TruleskIntentRule(PassListActivity::class.java, false)
|
var rule = TruleskIntentRule(PassListActivity::class.java, false)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.closeSoftKeyboard
|
import androidx.test.espresso.Espresso.closeSoftKeyboard
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.*
|
import androidx.test.espresso.action.ViewActions.*
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.doesNotExist
|
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import android.support.test.filters.SdkSuppress
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import android.support.test.runner.AndroidJUnit4
|
import androidx.test.filters.SdkSuppress
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -27,9 +27,11 @@ class TheBarCodeEditing {
|
||||||
|
|
||||||
val passStore: PassStore = App.kodein.instance()
|
val passStore: PassStore = App.kodein.instance()
|
||||||
|
|
||||||
lateinit var currentPass: PassImpl
|
private lateinit var currentPass: PassImpl
|
||||||
|
|
||||||
fun start(setupPass: (pass: PassImpl) -> Unit = {}) {
|
private fun start(setupPass: (pass: PassImpl) -> Unit = {}) {
|
||||||
|
|
||||||
|
TestApp.populatePassStoreWithSinglePass()
|
||||||
|
|
||||||
currentPass = passStore.currentPass as PassImpl
|
currentPass = passStore.currentPass as PassImpl
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Fail.fail
|
import org.assertj.core.api.Fail.fail
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -48,7 +47,6 @@ class TheBarcodeHelper {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
fail("could not create barcode", e)
|
fail("could not create barcode", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testBitmapSizeIsSane(format: PassBarCodeFormat) {
|
fun testBitmapSizeIsSane(format: PassBarCodeFormat) {
|
||||||
|
@ -59,6 +57,5 @@ class TheBarcodeHelper {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
fail("could not create barcode", e)
|
fail("could not create barcode", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withText
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import org.hamcrest.CoreMatchers.containsString
|
import org.hamcrest.CoreMatchers.containsString
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.ligi.passandroid.R.id.emptyView
|
import org.ligi.passandroid.R.id.emptyView
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.replaceText
|
import androidx.test.espresso.action.ViewActions.replaceText
|
||||||
import android.support.test.espresso.action.ViewActions.scrollTo
|
import androidx.test.espresso.action.ViewActions.scrollTo
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
|
@ -2,10 +2,10 @@ package org.ligi.passandroid
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -19,9 +19,9 @@ import org.ligi.passandroid.ui.FullscreenBarcodeActivity
|
||||||
import org.ligi.trulesk.TruleskIntentRule
|
import org.ligi.trulesk.TruleskIntentRule
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class TheFullscreenBarcodeActivity {
|
private const val BARCODE_MESSAGE = "2323"
|
||||||
|
|
||||||
private val BARCODE_MESSAGE = "2323"
|
class TheFullscreenBarcodeActivity {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var rule = TruleskIntentRule(FullscreenBarcodeActivity::class.java, false)
|
var rule = TruleskIntentRule(FullscreenBarcodeActivity::class.java, false)
|
||||||
|
@ -78,11 +78,11 @@ class TheFullscreenBarcodeActivity {
|
||||||
val bitmap = bitmapDrawable.bitmap
|
val bitmap = bitmapDrawable.bitmap
|
||||||
|
|
||||||
val bitmapToTest: Bitmap
|
val bitmapToTest: Bitmap
|
||||||
if (format === PassBarCodeFormat.AZTEC) {
|
bitmapToTest = if (format === PassBarCodeFormat.AZTEC) {
|
||||||
// not sure why - but for the decoder to pick up AZTEC it must have moar pixelz - smells like a zxing bug
|
// not sure why - but for the decoder to pick up AZTEC it must have moar pixelz - smells like a zxing bug
|
||||||
bitmapToTest = Bitmap.createScaledBitmap(bitmap, bitmap.width * 2, bitmap.height * 2, false)
|
Bitmap.createScaledBitmap(bitmap, bitmap.width * 2, bitmap.height * 2, false)
|
||||||
} else {
|
} else {
|
||||||
bitmapToTest = bitmap
|
bitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(bitmapToTest.decodeBarCode()).isEqualTo(BARCODE_MESSAGE)
|
assertThat(bitmapToTest.decodeBarCode()).isEqualTo(BARCODE_MESSAGE)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
|
@ -5,15 +5,15 @@ import android.app.Activity.RESULT_CANCELED
|
||||||
import android.app.Instrumentation.ActivityResult
|
import android.app.Instrumentation.ActivityResult
|
||||||
import android.content.Intent.ACTION_SEND
|
import android.content.Intent.ACTION_SEND
|
||||||
import android.content.Intent.ACTION_VIEW
|
import android.content.Intent.ACTION_VIEW
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.Espresso.pressBack
|
import androidx.test.espresso.Espresso.pressBack
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.contrib.DrawerActions.open
|
import androidx.test.espresso.contrib.DrawerActions.open
|
||||||
import android.support.test.espresso.intent.Intents.intended
|
import androidx.test.espresso.intent.Intents.intended
|
||||||
import android.support.test.espresso.intent.Intents.intending
|
import androidx.test.espresso.intent.Intents.intending
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.*
|
import androidx.test.espresso.intent.matcher.IntentMatchers.*
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.hamcrest.Matchers.allOf
|
import org.hamcrest.Matchers.allOf
|
||||||
import org.hamcrest.Matchers.not
|
import org.hamcrest.Matchers.not
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -61,19 +61,6 @@ class TheNavigationDrawer {
|
||||||
intended(allOf(hasAction(ACTION_VIEW), hasData("https://play.google.com/apps/testing/org.ligi.passandroid")))
|
intended(allOf(hasAction(ACTION_VIEW), hasData("https://play.google.com/apps/testing/org.ligi.passandroid")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testCommunityClick() {
|
|
||||||
testThatNavigationDrawerOpens()
|
|
||||||
rule.screenShot("open_drawer")
|
|
||||||
|
|
||||||
intending(hasAction(ACTION_VIEW)).respondWith(ActivityResult(RESULT_CANCELED, null))
|
|
||||||
|
|
||||||
onView(withText(nav_community_on_google)).perform(click())
|
|
||||||
|
|
||||||
intended(allOf(hasAction(ACTION_VIEW), hasData("https://plus.google.com/communities/116353894782342292067")))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGitHubClick() {
|
fun testGitHubClick() {
|
||||||
testThatNavigationDrawerOpens()
|
testThatNavigationDrawerOpens()
|
||||||
|
|
|
@ -4,18 +4,16 @@ import android.annotation.TargetApi
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Instrumentation
|
import android.app.Instrumentation
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.*
|
import androidx.test.espresso.action.ViewActions.*
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.intent.Intents.intended
|
import androidx.test.espresso.intent.Intents.intended
|
||||||
import android.support.test.espresso.intent.Intents.intending
|
import androidx.test.espresso.intent.Intents.intending
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.hasAction
|
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.ligi.passandroid.R.id.*
|
|
||||||
import org.ligi.passandroid.R.string.*
|
|
||||||
import org.ligi.passandroid.model.pass.PassType.COUPON
|
import org.ligi.passandroid.model.pass.PassType.COUPON
|
||||||
import org.ligi.passandroid.model.pass.PassType.EVENT
|
import org.ligi.passandroid.model.pass.PassType.EVENT
|
||||||
import org.ligi.passandroid.ui.PassEditActivity
|
import org.ligi.passandroid.ui.PassEditActivity
|
||||||
|
@ -27,15 +25,16 @@ class ThePassEditActivity {
|
||||||
val passStore = TestApp.passStore()
|
val passStore = TestApp.passStore()
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var rule = TruleskIntentRule(PassEditActivity::class.java)
|
var rule = TruleskIntentRule(PassEditActivity::class.java) {
|
||||||
|
TestApp.populatePassStoreWithSinglePass()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSetToEventWorks() {
|
fun testSetToEventWorks() {
|
||||||
|
onView(withId(R.id.categoryView)).perform(click())
|
||||||
|
|
||||||
onView(withId(categoryView)).perform(click())
|
onView(withText(R.string.select_category_dialog_title)).perform(click())
|
||||||
|
onView(withText(R.string.category_event)).perform(click())
|
||||||
onView(withText(select_category_dialog_title)).perform(click())
|
|
||||||
onView(withText(category_event)).perform(click())
|
|
||||||
assertThat(passStore.currentPass!!.type).isEqualTo(EVENT)
|
assertThat(passStore.currentPass!!.type).isEqualTo(EVENT)
|
||||||
|
|
||||||
rule.screenShot("edit_set_event")
|
rule.screenShot("edit_set_event")
|
||||||
|
@ -43,10 +42,10 @@ class ThePassEditActivity {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSetToCouponWorks() {
|
fun testSetToCouponWorks() {
|
||||||
onView(withId(categoryView)).perform(click())
|
onView(withId(R.id.categoryView)).perform(click())
|
||||||
|
|
||||||
onView(withText(select_category_dialog_title)).perform(click())
|
onView(withText(R.string.select_category_dialog_title)).perform(click())
|
||||||
onView(withText(category_coupon)).perform(click())
|
onView(withText(R.string.category_coupon)).perform(click())
|
||||||
assertThat(passStore.currentPass!!.type).isEqualTo(COUPON)
|
assertThat(passStore.currentPass!!.type).isEqualTo(COUPON)
|
||||||
|
|
||||||
rule.screenShot("edit_set_coupon")
|
rule.screenShot("edit_set_coupon")
|
||||||
|
@ -55,7 +54,7 @@ class ThePassEditActivity {
|
||||||
@Test
|
@Test
|
||||||
fun testSetDescriptionWorks() {
|
fun testSetDescriptionWorks() {
|
||||||
|
|
||||||
onView(withId(passTitle)).perform(clearText(), typeText("test description"))
|
onView(withId(R.id.passTitle)).perform(clearText(), typeText("test description"))
|
||||||
assertThat(passStore.currentPass!!.description).isEqualTo("test description")
|
assertThat(passStore.currentPass!!.description).isEqualTo("test description")
|
||||||
|
|
||||||
rule.screenShot("edit_set_description")
|
rule.screenShot("edit_set_description")
|
||||||
|
@ -65,10 +64,10 @@ class ThePassEditActivity {
|
||||||
@Test
|
@Test
|
||||||
fun testColorWheelIsThere() {
|
fun testColorWheelIsThere() {
|
||||||
|
|
||||||
onView(withId(categoryView)).perform(click())
|
onView(withId(R.id.categoryView)).perform(click())
|
||||||
onView(withText(change_color_dialog_title)).perform(click())
|
onView(withText(R.string.change_color_dialog_title)).perform(click())
|
||||||
|
|
||||||
onView(withId(colorPicker)).check(matches(isDisplayed()))
|
onView(withId(R.id.colorPicker)).check(matches(isDisplayed()))
|
||||||
|
|
||||||
rule.screenShot("edit_set_color")
|
rule.screenShot("edit_set_color")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ package org.ligi.passandroid
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.Espresso.pressBack
|
import androidx.test.espresso.Espresso.pressBack
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.ligi.passandroid.R.id.pass_recyclerview
|
import org.ligi.passandroid.R.id.pass_recyclerview
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.action.ViewActions.typeText
|
import androidx.test.espresso.action.ViewActions.typeText
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -14,6 +14,8 @@ import org.ligi.passandroid.ui.PassListActivity
|
||||||
import org.ligi.passandroid.ui.PassListFragment
|
import org.ligi.passandroid.ui.PassListFragment
|
||||||
import org.ligi.trulesk.TruleskIntentRule
|
import org.ligi.trulesk.TruleskIntentRule
|
||||||
|
|
||||||
|
const val CUSTOM_PROBE = "FOO_PROBE"
|
||||||
|
|
||||||
class ThePassListSwiping {
|
class ThePassListSwiping {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
|
@ -42,7 +44,6 @@ class ThePassListSwiping {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testWeCanMoveToCustom() {
|
fun testWeCanMoveToCustom() {
|
||||||
val CUSTOM_PROBE = "FOO_PROBE"
|
|
||||||
|
|
||||||
fakeSwipeLeft()
|
fakeSwipeLeft()
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.doesNotExist
|
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import org.hamcrest.core.IsNot.not
|
import org.hamcrest.core.IsNot.not
|
||||||
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.ligi.passandroid.model.pass.BarCode
|
import org.ligi.passandroid.model.pass.BarCode
|
||||||
|
@ -21,11 +22,16 @@ import java.util.*
|
||||||
@TargetApi(14)
|
@TargetApi(14)
|
||||||
class ThePassViewActivity {
|
class ThePassViewActivity {
|
||||||
|
|
||||||
internal fun getActPass() = TestApp.passStore().currentPass as PassImpl
|
private fun getActPass() = TestApp.passStore().currentPass as PassImpl
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var rule = TruleskActivityRule(PassViewActivity::class.java, false)
|
var rule = TruleskActivityRule(PassViewActivity::class.java, false)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun before() {
|
||||||
|
TestApp.populatePassStoreWithSinglePass()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testThatDescriptionIsThere() {
|
fun testThatDescriptionIsThere() {
|
||||||
rule.launchActivity(null)
|
rule.launchActivity(null)
|
||||||
|
@ -35,7 +41,7 @@ class ThePassViewActivity {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDateIsGoneWhenPassbookHasNoDate() {
|
fun testDateIsGoneWhenPassbookHasNoDate() {
|
||||||
getActPass().validTimespans = ArrayList<PassImpl.TimeSpan>()
|
getActPass().validTimespans = ArrayList()
|
||||||
rule.launchActivity(null)
|
rule.launchActivity(null)
|
||||||
|
|
||||||
onView(withId(R.id.date)).check(matches(not(isDisplayed())))
|
onView(withId(R.id.date)).check(matches(not(isDisplayed())))
|
||||||
|
@ -92,7 +98,7 @@ class ThePassViewActivity {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLinkToCalendarIsNotThereWhenPassbookHasNoDate() {
|
fun testLinkToCalendarIsNotThereWhenPassbookHasNoDate() {
|
||||||
getActPass().validTimespans = ArrayList<PassImpl.TimeSpan>()
|
getActPass().validTimespans = ArrayList()
|
||||||
rule.launchActivity(null)
|
rule.launchActivity(null)
|
||||||
|
|
||||||
onView(withText(R.string.pass_to_calendar)).check(matches(not(isDisplayed())))
|
onView(withText(R.string.pass_to_calendar)).check(matches(not(isDisplayed())))
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.assertion.ViewAssertions
|
import androidx.test.espresso.assertion.ViewAssertions
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import org.hamcrest.CoreMatchers.not
|
import org.hamcrest.CoreMatchers.not
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -16,7 +16,10 @@ import org.threeten.bp.ZonedDateTime
|
||||||
|
|
||||||
class ThePassViewHolder {
|
class ThePassViewHolder {
|
||||||
|
|
||||||
val currentPass by lazy { App.passStore.currentPass as PassImpl }
|
private val currentPass by lazy {
|
||||||
|
TestApp.populatePassStoreWithSinglePass()
|
||||||
|
App.passStore.currentPass as PassImpl
|
||||||
|
}
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var rule = TruleskActivityRule(PassListActivity::class.java, false)
|
var rule = TruleskActivityRule(PassListActivity::class.java, false)
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ligi.passandroid
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.support.test.InstrumentationRegistry.getInstrumentation
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -17,13 +17,14 @@ class ThePastLocationsStore {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var rule = TruleskActivityRule(PassViewActivity::class.java) {
|
var rule = TruleskActivityRule(PassViewActivity::class.java) {
|
||||||
|
TestApp.populatePassStoreWithSinglePass()
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
lateinit var tracker: Tracker
|
lateinit var tracker: Tracker
|
||||||
|
|
||||||
val prefs: SharedPreferences by lazy { getInstrumentation().context.getSharedPreferences("" + System.currentTimeMillis() / 100000, Context.MODE_PRIVATE) }
|
private val prefs: SharedPreferences by lazy { InstrumentationRegistry.getInstrumentation().context.getSharedPreferences("" + System.currentTimeMillis() / 100000, Context.MODE_PRIVATE) }
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
|
@ -34,7 +35,7 @@ class ThePastLocationsStore {
|
||||||
fun testPastLocationsStoreShouldNeverContainMoreThanMaxElements() {
|
fun testPastLocationsStoreShouldNeverContainMoreThanMaxElements() {
|
||||||
val tested = PastLocationsStore(prefs, tracker)
|
val tested = PastLocationsStore(prefs, tracker)
|
||||||
|
|
||||||
for (i in 0..PastLocationsStore.MAX_ELEMENTS * 2 - 1) {
|
for (i in 0 until PastLocationsStore.MAX_ELEMENTS * 2) {
|
||||||
tested.putLocation("" + i)
|
tested.putLocation("" + i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ class ThePastLocationsStore {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPastLocationsStoreShouldStoreOnlyOneOfAKind() {
|
fun testPastLocationsStoreShouldStoreOnlyOneOfAKind() {
|
||||||
val tested = PastLocationsStore(prefs, tracker!!)
|
val tested = PastLocationsStore(prefs, tracker)
|
||||||
|
|
||||||
for (i in 0..2) {
|
for (i in 0..2) {
|
||||||
tested.putLocation("foo")
|
tested.putLocation("foo")
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withText
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import android.support.v7.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -20,7 +20,7 @@ class ThePreferenceActivity {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val rule = TruleskActivityRule(PreferenceActivity::class.java)
|
val rule = TruleskActivityRule(PreferenceActivity::class.java)
|
||||||
|
|
||||||
val androidSettings by lazy { AndroidSettings(rule.activity) }
|
private val androidSettings by lazy { AndroidSettings(rule.activity) }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun autoLightToggles() {
|
fun autoLightToggles() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ligi.passandroid;
|
package org.ligi.passandroid;
|
||||||
|
|
||||||
import android.support.test.InstrumentationRegistry;
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -27,7 +27,7 @@ public class TheUnzipPassController {
|
||||||
PassStore passStore;
|
PassStore passStore;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package org.ligi.passandroid.functions
|
package org.ligi.passandroid.functions
|
||||||
|
|
||||||
import android.support.test.espresso.UiController
|
import androidx.test.espresso.UiController
|
||||||
import android.support.test.espresso.ViewAction
|
import androidx.test.espresso.ViewAction
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom
|
import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import net.i2p.android.ext.floatingactionbutton.FloatingActionsMenu
|
import net.i2p.android.ext.floatingactionbutton.FloatingActionsMenu
|
||||||
import org.hamcrest.Description
|
import org.hamcrest.Description
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package org.ligi.passandroid.functions
|
package org.ligi.passandroid.functions
|
||||||
|
|
||||||
import android.support.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
|
|
||||||
|
|
||||||
fun checkThatHelpIsThere() {
|
fun checkThatHelpIsThere() {
|
||||||
onView(withId(R.id.help_text)).check(matches(isDisplayed()))
|
onView(withId(R.id.help_text)).check(matches(isDisplayed()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.functions
|
package org.ligi.passandroid.functions
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.test.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.assertj.core.api.Fail.fail
|
import org.assertj.core.api.Fail.fail
|
||||||
import org.ligi.passandroid.model.InputStreamWithSource
|
import org.ligi.passandroid.model.InputStreamWithSource
|
||||||
import org.ligi.passandroid.model.PassStore
|
import org.ligi.passandroid.model.PassStore
|
||||||
|
|
|
@ -10,7 +10,7 @@ class FixedPassListPassStore(private var passes: List<Pass>) : PassStore {
|
||||||
override lateinit var classifier: PassClassifier
|
override lateinit var classifier: PassClassifier
|
||||||
|
|
||||||
init {
|
init {
|
||||||
classifier = PassClassifier(HashMap<String, String>(), this)
|
classifier = PassClassifier(HashMap(), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setList(newPasses: List<Pass>, newCurrentPass: Pass? = newPasses.firstOrNull()) {
|
fun setList(newPasses: List<Pass>, newCurrentPass: Pass? = newPasses.firstOrNull()) {
|
||||||
|
@ -19,7 +19,7 @@ class FixedPassListPassStore(private var passes: List<Pass>) : PassStore {
|
||||||
passMap.clear()
|
passMap.clear()
|
||||||
passMap.putAll(createHashMap())
|
passMap.putAll(createHashMap())
|
||||||
|
|
||||||
classifier = PassClassifier(HashMap<String, String>(), this)
|
classifier = PassClassifier(HashMap(), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var currentPass: Pass? = null
|
override var currentPass: Pass? = null
|
||||||
|
@ -31,7 +31,7 @@ class FixedPassListPassStore(private var passes: List<Pass>) : PassStore {
|
||||||
private fun createHashMap(): HashMap<String, Pass> {
|
private fun createHashMap(): HashMap<String, Pass> {
|
||||||
val hashMap = HashMap<String, Pass>()
|
val hashMap = HashMap<String, Pass>()
|
||||||
|
|
||||||
passes.forEach { hashMap.put(it.id, it) }
|
passes.forEach { hashMap[it.id] = it }
|
||||||
return hashMap
|
return hashMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".InstallListener"
|
android:name=".InstallListener"
|
||||||
|
android:permission="android.permission.INSTALL_PACKAGES"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.android.vending.INSTALL_REFERRER"/>
|
<action android:name="com.android.vending.INSTALL_REFERRER"/>
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="android.support.v4.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="@string/authority_fileprovider"
|
android:authorities="@string/authority_fileprovider"
|
||||||
android:grantUriPermissions="true"
|
android:grantUriPermissions="true"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
|
@ -122,47 +123,35 @@
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
|
||||||
<data android:mimeType="application/vnd.espass-espass"/>
|
<data android:scheme="http" android:mimeType="application/vnd.espass-espass"/>
|
||||||
</intent-filter>
|
<data android:scheme="https" android:mimeType="application/vnd.espass-espass"/>
|
||||||
<intent-filter>
|
<data android:scheme="content" android:mimeType="application/vnd.espass-espass"/>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<data android:scheme="file" android:mimeType="application/vnd.espass-espass"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<data android:scheme="http" android:mimeType="application/vnd.espass-espass+zip"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<data android:scheme="https" android:mimeType="application/vnd.espass-espass+zip"/>
|
||||||
|
<data android:scheme="content" android:mimeType="application/vnd.espass-espass+zip"/>
|
||||||
|
<data android:scheme="file" android:mimeType="application/vnd.espass-espass+zip"/>
|
||||||
|
|
||||||
<data android:mimeType="application/vnd.espass-espass+zip"/>
|
<data android:scheme="http" android:mimeType="application/vnd.apple.pkpass"/>
|
||||||
</intent-filter>
|
<data android:scheme="https" android:mimeType="application/vnd.apple.pkpass"/>
|
||||||
<intent-filter>
|
<data android:scheme="content" android:mimeType="application/vnd.apple.pkpass"/>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<data android:scheme="file" android:mimeType="application/vnd.apple.pkpass"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<data android:scheme="http" android:mimeType="application/pkpass"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<data android:scheme="https" android:mimeType="application/pkpass"/>
|
||||||
|
<data android:scheme="content" android:mimeType="application/pkpass"/>
|
||||||
|
<data android:scheme="file" android:mimeType="application/pkpass"/>
|
||||||
|
|
||||||
<data android:mimeType="application/vnd.apple.pkpass"/>
|
<data android:scheme="http" android:mimeType="application/vndapplepkpass"/>
|
||||||
</intent-filter>
|
<data android:scheme="https" android:mimeType="application/vndapplepkpass"/>
|
||||||
<intent-filter>
|
<data android:scheme="content" android:mimeType="application/vndapplepkpass"/>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<data android:scheme="file" android:mimeType="application/vndapplepkpass"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<data android:scheme="http" android:mimeType="application/vnd-com.apple.pkpass"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<data android:scheme="https" android:mimeType="application/vnd-com.apple.pkpass"/>
|
||||||
|
<data android:scheme="content" android:mimeType="application/vnd-com.apple.pkpass"/>
|
||||||
<data android:mimeType="application/pkpass"/>
|
<data android:scheme="file" android:mimeType="application/vnd-com.apple.pkpass"/>
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
|
||||||
|
|
||||||
<data android:mimeType="application/vndapplepkpass"/>
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
|
||||||
|
|
||||||
<data android:mimeType="application/vnd-com.apple.pkpass"/>
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -616,17 +605,9 @@
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
|
||||||
<data android:mimeType="application/x-pdf"/>
|
<data android:scheme="content" android:mimeType="application/x-pdf"/>
|
||||||
|
<data android:scheme="content" android:mimeType="application/pdf"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
|
||||||
|
|
||||||
<data android:mimeType="application/pdf"/>
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
|
||||||
|
@ -1071,22 +1052,6 @@
|
||||||
android:pathPattern="/.*\\.pkpass"
|
android:pathPattern="/.*\\.pkpass"
|
||||||
android:scheme="content"/>
|
android:scheme="content"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
|
||||||
|
|
||||||
<data android:mimeType="application/vnd.apple.pkpass"/>
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
|
||||||
|
|
||||||
<data android:mimeType="application/vnd-com.apple.pkpass"/>
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/**
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005-2014, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -35,6 +35,7 @@ import java.util.List;
|
||||||
* <p/>
|
* <p/>
|
||||||
* @stable ICU 3.4
|
* @stable ICU 3.4
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
public class CharsetDetector {
|
public class CharsetDetector {
|
||||||
|
|
||||||
// Question: Should we have getters corresponding to the setters for input text
|
// Question: Should we have getters corresponding to the setters for input text
|
||||||
|
@ -182,7 +183,7 @@ public class CharsetDetector {
|
||||||
* @stable ICU 3.4
|
* @stable ICU 3.4
|
||||||
*/
|
*/
|
||||||
public CharsetMatch[] detectAll() {
|
public CharsetMatch[] detectAll() {
|
||||||
ArrayList<CharsetMatch> matches = new ArrayList<CharsetMatch>();
|
ArrayList<CharsetMatch> matches = new ArrayList<>();
|
||||||
|
|
||||||
MungeInput(); // Strip html markup, collect byte stats.
|
MungeInput(); // Strip html markup, collect byte stats.
|
||||||
|
|
||||||
|
@ -344,7 +345,7 @@ public class CharsetDetector {
|
||||||
* it by removing what appears to be html markup.
|
* it by removing what appears to be html markup.
|
||||||
*/
|
*/
|
||||||
private void MungeInput() {
|
private void MungeInput() {
|
||||||
int srci = 0;
|
int srci;
|
||||||
int dsti = 0;
|
int dsti = 0;
|
||||||
byte b;
|
byte b;
|
||||||
boolean inMarkup = false;
|
boolean inMarkup = false;
|
||||||
|
@ -473,7 +474,7 @@ public class CharsetDetector {
|
||||||
private static final List<CSRecognizerInfo> ALL_CS_RECOGNIZERS;
|
private static final List<CSRecognizerInfo> ALL_CS_RECOGNIZERS;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
List<CSRecognizerInfo> list = new ArrayList<CSRecognizerInfo>();
|
List<CSRecognizerInfo> list = new ArrayList<>();
|
||||||
|
|
||||||
list.add(new CSRecognizerInfo(new CharsetRecog_UTF8(), true));
|
list.add(new CSRecognizerInfo(new CharsetRecog_UTF8(), true));
|
||||||
list.add(new CSRecognizerInfo(new CharsetRecog_Unicode.CharsetRecog_UTF_16_BE(), true));
|
list.add(new CSRecognizerInfo(new CharsetRecog_Unicode.CharsetRecog_UTF_16_BE(), true));
|
||||||
|
@ -522,7 +523,7 @@ public class CharsetDetector {
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String[] getDetectableCharsets() {
|
public String[] getDetectableCharsets() {
|
||||||
List<String> csnames = new ArrayList<String>(ALL_CS_RECOGNIZERS.size());
|
List<String> csnames = new ArrayList<>(ALL_CS_RECOGNIZERS.size());
|
||||||
for (int i = 0; i < ALL_CS_RECOGNIZERS.size(); i++) {
|
for (int i = 0; i < ALL_CS_RECOGNIZERS.size(); i++) {
|
||||||
CSRecognizerInfo rcinfo = ALL_CS_RECOGNIZERS.get(i);
|
CSRecognizerInfo rcinfo = ALL_CS_RECOGNIZERS.get(i);
|
||||||
boolean active = (fEnabledRecognizers == null) ? rcinfo.isDefaultEnabled : fEnabledRecognizers[i];
|
boolean active = (fEnabledRecognizers == null) ? rcinfo.isDefaultEnabled : fEnabledRecognizers[i];
|
||||||
|
@ -530,7 +531,7 @@ public class CharsetDetector {
|
||||||
csnames.add(rcinfo.recognizer.getName());
|
csnames.add(rcinfo.recognizer.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return csnames.toArray(new String[csnames.size()]);
|
return csnames.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/**
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005-2012, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
@ -26,6 +26,7 @@ import java.io.Reader;
|
||||||
*
|
*
|
||||||
* @stable ICU 3.4
|
* @stable ICU 3.4
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
public class CharsetMatch implements Comparable<CharsetMatch> {
|
public class CharsetMatch implements Comparable<CharsetMatch> {
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,13 +86,13 @@ public class CharsetMatch implements Comparable<CharsetMatch> {
|
||||||
* @stable ICU 3.4
|
* @stable ICU 3.4
|
||||||
*/
|
*/
|
||||||
public String getString(int maxLength) throws java.io.IOException {
|
public String getString(int maxLength) throws java.io.IOException {
|
||||||
String result = null;
|
String result;
|
||||||
if (fInputStream != null) {
|
if (fInputStream != null) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
char[] buffer = new char[1024];
|
char[] buffer = new char[1024];
|
||||||
Reader reader = getReader();
|
Reader reader = getReader();
|
||||||
int max = maxLength < 0? Integer.MAX_VALUE : maxLength;
|
int max = maxLength < 0? Integer.MAX_VALUE : maxLength;
|
||||||
int bytesRead = 0;
|
int bytesRead;
|
||||||
|
|
||||||
while ((bytesRead = reader.read(buffer, 0, Math.min(max, 1024))) >= 0) {
|
while ((bytesRead = reader.read(buffer, 0, Math.min(max, 1024))) >= 0) {
|
||||||
sb.append(buffer, 0, bytesRead);
|
sb.append(buffer, 0, bytesRead);
|
||||||
|
@ -108,6 +109,7 @@ public class CharsetMatch implements Comparable<CharsetMatch> {
|
||||||
* be used to open a charset (e.g. IBM424_rtl). The ending '_rtl' or 'ltr'
|
* be used to open a charset (e.g. IBM424_rtl). The ending '_rtl' or 'ltr'
|
||||||
* should be stripped off before creating the string.
|
* should be stripped off before creating the string.
|
||||||
*/
|
*/
|
||||||
|
//noinspection IndexOfReplaceableByContains
|
||||||
int startSuffix = name.indexOf("_rtl") < 0 ? name.indexOf("_ltr") : name.indexOf("_rtl");
|
int startSuffix = name.indexOf("_rtl") < 0 ? name.indexOf("_ltr") : name.indexOf("_rtl");
|
||||||
if (startSuffix > 0) {
|
if (startSuffix > 0) {
|
||||||
name = name.substring(0, startSuffix);
|
name = name.substring(0, startSuffix);
|
||||||
|
@ -234,7 +236,7 @@ public class CharsetMatch implements Comparable<CharsetMatch> {
|
||||||
// If user gave us a byte array, this is it.
|
// If user gave us a byte array, this is it.
|
||||||
private int fRawLength; // Length of data in fRawInput array.
|
private int fRawLength; // Length of data in fRawInput array.
|
||||||
|
|
||||||
private InputStream fInputStream = null; // User's input stream, or null if the user
|
private InputStream fInputStream; // User's input stream, or null if the user
|
||||||
// gave us a byte array.
|
// gave us a byte array.
|
||||||
|
|
||||||
private String fCharsetName; // The name of the charset this CharsetMatch
|
private String fCharsetName; // The name of the charset this CharsetMatch
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,6 +14,7 @@ package com.ibm.icu.text;
|
||||||
*
|
*
|
||||||
* The separate classes are nested within this class.
|
* The separate classes are nested within this class.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
abstract class CharsetRecog_2022 extends CharsetRecognizer {
|
abstract class CharsetRecog_2022 extends CharsetRecognizer {
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ abstract class CharsetRecog_2022 extends CharsetRecognizer {
|
||||||
byte [] seq = escapeSequences[escN];
|
byte [] seq = escapeSequences[escN];
|
||||||
|
|
||||||
if ((textLen - i) < seq.length) {
|
if ((textLen - i) < seq.length) {
|
||||||
continue checkEscapes;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j=1; j<seq.length; j++) {
|
for (j=1; j<seq.length; j++) {
|
||||||
|
@ -92,9 +93,6 @@ abstract class CharsetRecog_2022 extends CharsetRecognizer {
|
||||||
return quality;
|
return quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static class CharsetRecog_2022JP extends CharsetRecog_2022 {
|
static class CharsetRecog_2022JP extends CharsetRecog_2022 {
|
||||||
private byte [] [] escapeSequences = {
|
private byte [] [] escapeSequences = {
|
||||||
{0x1b, 0x24, 0x28, 0x43}, // KS X 1001:1992
|
{0x1b, 0x24, 0x28, 0x43}, // KS X 1001:1992
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
/**
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005 - 2014, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Charset recognizer for UTF-8
|
* Charset recognizer for UTF-8
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
class CharsetRecog_UTF8 extends CharsetRecognizer {
|
class CharsetRecog_UTF8 extends CharsetRecognizer {
|
||||||
|
|
||||||
String getName() {
|
String getName() {
|
||||||
|
@ -24,7 +25,7 @@ class CharsetRecog_UTF8 extends CharsetRecognizer {
|
||||||
int numInvalid = 0;
|
int numInvalid = 0;
|
||||||
byte input[] = det.fRawInput;
|
byte input[] = det.fRawInput;
|
||||||
int i;
|
int i;
|
||||||
int trailBytes = 0;
|
int trailBytes;
|
||||||
int confidence;
|
int confidence;
|
||||||
|
|
||||||
if (det.fRawLength >= 3 &&
|
if (det.fRawLength >= 3 &&
|
||||||
|
|
|
@ -12,6 +12,7 @@ package com.ibm.icu.text;
|
||||||
* This class matches UTF-16 and UTF-32, both big- and little-endian. The
|
* This class matches UTF-16 and UTF-32, both big- and little-endian. The
|
||||||
* BOM will be used if it is present.
|
* BOM will be used if it is present.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
abstract class CharsetRecog_Unicode extends CharsetRecognizer {
|
abstract class CharsetRecog_Unicode extends CharsetRecognizer {
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -171,7 +172,7 @@ abstract class CharsetRecog_Unicode extends CharsetRecognizer {
|
||||||
{
|
{
|
||||||
int getChar(byte[] input, int index)
|
int getChar(byte[] input, int index)
|
||||||
{
|
{
|
||||||
return (input[index + 0] & 0xFF) << 24 | (input[index + 1] & 0xFF) << 16 |
|
return (input[index] & 0xFF) << 24 | (input[index + 1] & 0xFF) << 16 |
|
||||||
(input[index + 2] & 0xFF) << 8 | (input[index + 3] & 0xFF);
|
(input[index + 2] & 0xFF) << 8 | (input[index + 3] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ abstract class CharsetRecog_Unicode extends CharsetRecognizer {
|
||||||
int getChar(byte[] input, int index)
|
int getChar(byte[] input, int index)
|
||||||
{
|
{
|
||||||
return (input[index + 3] & 0xFF) << 24 | (input[index + 2] & 0xFF) << 16 |
|
return (input[index + 3] & 0xFF) << 24 | (input[index + 2] & 0xFF) << 16 |
|
||||||
(input[index + 1] & 0xFF) << 8 | (input[index + 0] & 0xFF);
|
(input[index + 1] & 0xFF) << 8 | (input[index] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getName()
|
String getName()
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
/*
|
/*
|
||||||
****************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005-2012, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
****************************************************************************
|
*******************************************************************************
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
|
@ -21,6 +20,7 @@ import java.util.Arrays;
|
||||||
* encodings to be checked. The specific encoding being recognized
|
* encodings to be checked. The specific encoding being recognized
|
||||||
* is determined by subclass.
|
* is determined by subclass.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,8 +157,7 @@ abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
done = true;
|
done = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int byteValue = (int)det.fRawInput[nextIndex++] & 0x00ff;
|
return (int)det.fRawInput[nextIndex++] & 0x00ff;
|
||||||
return byteValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,9 +320,9 @@ abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
boolean nextChar(iteratedChar it, CharsetDetector det) {
|
boolean nextChar(iteratedChar it, CharsetDetector det) {
|
||||||
it.index = it.nextIndex;
|
it.index = it.nextIndex;
|
||||||
it.error = false;
|
it.error = false;
|
||||||
int firstByte = 0;
|
int firstByte;
|
||||||
int secondByte = 0;
|
int secondByte;
|
||||||
int thirdByte = 0;
|
int thirdByte;
|
||||||
//int fourthByte = 0;
|
//int fourthByte = 0;
|
||||||
|
|
||||||
buildChar: {
|
buildChar: {
|
||||||
|
@ -372,7 +371,7 @@ abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (it.done == false);
|
return (!it.done);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -461,10 +460,10 @@ abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
boolean nextChar(iteratedChar it, CharsetDetector det) {
|
boolean nextChar(iteratedChar it, CharsetDetector det) {
|
||||||
it.index = it.nextIndex;
|
it.index = it.nextIndex;
|
||||||
it.error = false;
|
it.error = false;
|
||||||
int firstByte = 0;
|
int firstByte;
|
||||||
int secondByte = 0;
|
int secondByte;
|
||||||
int thirdByte = 0;
|
int thirdByte;
|
||||||
int fourthByte = 0;
|
int fourthByte;
|
||||||
|
|
||||||
buildChar: {
|
buildChar: {
|
||||||
firstByte = it.charValue = it.nextByte(det);
|
firstByte = it.charValue = it.nextByte(det);
|
||||||
|
@ -483,7 +482,7 @@ abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
secondByte = it.nextByte(det);
|
secondByte = it.nextByte(det);
|
||||||
it.charValue = (it.charValue << 8) | secondByte;
|
it.charValue = (it.charValue << 8) | secondByte;
|
||||||
|
|
||||||
if (firstByte >= 0x81 && firstByte <= 0xFE) {
|
if (firstByte <= 0xFE) {
|
||||||
// Two byte Char
|
// Two byte Char
|
||||||
if ((secondByte >= 0x40 && secondByte <= 0x7E) || (secondByte >=80 && secondByte <=0xFE)) {
|
if ((secondByte >= 0x40 && secondByte <= 0x7E) || (secondByte >=80 && secondByte <=0xFE)) {
|
||||||
break buildChar;
|
break buildChar;
|
||||||
|
@ -504,11 +503,10 @@ abstract class CharsetRecog_mbcs extends CharsetRecognizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
it.error = true;
|
it.error = true;
|
||||||
break buildChar;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (it.done == false);
|
return !it.done;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int [] commonChars =
|
static int [] commonChars =
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
/*
|
/*
|
||||||
****************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005-2013, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
************************************************************************** *
|
*******************************************************************************
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class recognizes single-byte encodings. Because the encoding scheme is so
|
* This class recognizes single-byte encodings. Because the encoding scheme is so
|
||||||
* simple, language statistics are used to do the matching.
|
* simple, language statistics are used to do the matching.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
abstract class CharsetRecog_sbcs extends CharsetRecognizer {
|
abstract class CharsetRecog_sbcs extends CharsetRecognizer {
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -25,7 +24,7 @@ abstract class CharsetRecog_sbcs extends CharsetRecognizer {
|
||||||
private static final int N_GRAM_MASK = 0xFFFFFF;
|
private static final int N_GRAM_MASK = 0xFFFFFF;
|
||||||
|
|
||||||
protected int byteIndex = 0;
|
protected int byteIndex = 0;
|
||||||
private int ngram = 0;
|
private int ngram;
|
||||||
|
|
||||||
private int[] ngramList;
|
private int[] ngramList;
|
||||||
protected byte[] byteMap;
|
protected byte[] byteMap;
|
||||||
|
@ -273,7 +272,7 @@ abstract class CharsetRecog_sbcs extends CharsetRecognizer {
|
||||||
return parser.parse(det, spaceChar);
|
return parser.parse(det, spaceChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
int matchIBM420(CharsetDetector det, int[] ngrams, byte[] byteMap, byte spaceChar){
|
int matchIBM420(CharsetDetector det, int[] ngrams, byte[] byteMap, @SuppressWarnings("SameParameterValue") byte spaceChar){
|
||||||
NGramParser_IBM420 parser = new NGramParser_IBM420(ngrams, byteMap);
|
NGramParser_IBM420 parser = new NGramParser_IBM420(ngrams, byteMap);
|
||||||
return parser.parse(det, spaceChar);
|
return parser.parse(det, spaceChar);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/**
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* Copyright (C) 2005-2012, International Business Machines Corporation and *
|
* Copyright (C) 2005 - 2012, International Business Machines Corporation and *
|
||||||
* others. All Rights Reserved. *
|
* others. All Rights Reserved. *
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
package com.ibm.icu.text;
|
package com.ibm.icu.text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,7 @@ package com.ibm.icu.text;
|
||||||
* The WILL be shared by multiple instances of CharsetDetector.
|
* The WILL be shared by multiple instances of CharsetDetector.
|
||||||
* They encapsulate const charset-specific information.
|
* They encapsulate const charset-specific information.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
abstract class CharsetRecognizer {
|
abstract class CharsetRecognizer {
|
||||||
/**
|
/**
|
||||||
* Get the IANA name of this charset.
|
* Get the IANA name of this charset.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid
|
package org.ligi.passandroid
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.support.v7.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import com.github.salomonbrys.kodein.*
|
import com.github.salomonbrys.kodein.*
|
||||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||||
import com.squareup.leakcanary.LeakCanary
|
import com.squareup.leakcanary.LeakCanary
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid;
|
package org.ligi.passandroid;
|
||||||
|
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
public interface Tracker {
|
public interface Tracker {
|
||||||
void trackException(String s, Throwable e, boolean fatal);
|
void trackException(String s, Throwable e, boolean fatal);
|
||||||
|
|
|
@ -3,15 +3,15 @@ package org.ligi.passandroid.functions
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import android.support.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import android.support.design.widget.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.model.pass.Pass
|
import org.ligi.passandroid.model.pass.Pass
|
||||||
import org.ligi.passandroid.model.pass.PassImpl
|
import org.ligi.passandroid.model.pass.PassImpl
|
||||||
|
|
||||||
val DEFAULT_EVENT_LENGTH_IN_HOURS = 8L
|
const val DEFAULT_EVENT_LENGTH_IN_HOURS = 8L
|
||||||
|
|
||||||
fun tryAddDateToCalendar(pass: Pass, contextView: View, timeSpan: PassImpl.TimeSpan) {
|
fun tryAddDateToCalendar(pass: Pass, contextView: View, timeSpan: PassImpl.TimeSpan) {
|
||||||
if (pass.calendarTimespan == null) {
|
if (pass.calendarTimespan == null) {
|
||||||
|
|
|
@ -33,26 +33,26 @@ fun generateBarCodeBitmap(data: String, type: PassBarCodeFormat): Bitmap? {
|
||||||
|
|
||||||
// create buffered image to draw to
|
// create buffered image to draw to
|
||||||
// NTFS Bitmap.Config.ALPHA_8 sounds like an awesome idea - been there - done that ..
|
// NTFS Bitmap.Config.ALPHA_8 sounds like an awesome idea - been there - done that ..
|
||||||
val barcode_image = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
|
val barcodeImage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
|
||||||
|
|
||||||
// iterate through the matrix and draw the pixels to the image
|
// iterate through the matrix and draw the pixels to the image
|
||||||
for (y in 0..height - 1) {
|
for (y in 0 until height) {
|
||||||
for (x in 0..width - 1) {
|
for (x in 0 until width) {
|
||||||
barcode_image.setPixel(x, y, if (matrix.get(x, if (is1D) 0 else y)) 0 else 0xFFFFFF)
|
barcodeImage.setPixel(x, y, if (matrix.get(x, if (is1D) 0 else y)) 0 else 0xFFFFFF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return barcode_image
|
return barcodeImage
|
||||||
} catch (e: com.google.zxing.WriterException) {
|
} catch (e: com.google.zxing.WriterException) {
|
||||||
Log.w("could not write image " + e)
|
Log.w("could not write image: $e")
|
||||||
// TODO check if we should better return some rescue Image here
|
// TODO check if we should better return some rescue Image here
|
||||||
return null
|
return null
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
Log.w("could not write image " + e)
|
Log.w("could not write image: $e")
|
||||||
return null
|
return null
|
||||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||||
// happens for ITF barcode on certain inputs
|
// happens for ITF barcode on certain inputs
|
||||||
Log.w("could not write image " + e)
|
Log.w("could not write image: $e")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package org.ligi.passandroid.functions
|
package org.ligi.passandroid.functions
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.support.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import android.support.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import android.support.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.model.pass.PassType
|
import org.ligi.passandroid.model.pass.PassType
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.ligi.passandroid.model.InputStreamWithSource
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
val IPHONE_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53"
|
const val IPHONE_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53"
|
||||||
|
|
||||||
fun fromURI(context: Context, uri: Uri): InputStreamWithSource? {
|
fun fromURI(context: Context, uri: Uri): InputStreamWithSource? {
|
||||||
App.tracker.trackEvent("protocol", "to_inputstream", uri.scheme, null)
|
App.tracker.trackEvent("protocol", "to_inputstream", uri.scheme, null)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.functions
|
package org.ligi.passandroid.functions
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.support.design.widget.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.model.PassClassifier
|
import org.ligi.passandroid.model.PassClassifier
|
||||||
import org.ligi.passandroid.model.pass.Pass
|
import org.ligi.passandroid.model.pass.Pass
|
||||||
|
@ -9,7 +9,7 @@ import org.ligi.passandroid.model.pass.Pass
|
||||||
fun moveWithUndoSnackbar(passClassifier: PassClassifier, pass: Pass, topic: String, activity: Activity) {
|
fun moveWithUndoSnackbar(passClassifier: PassClassifier, pass: Pass, topic: String, activity: Activity) {
|
||||||
val oldTopic = passClassifier.getTopic(pass, "")
|
val oldTopic = passClassifier.getTopic(pass, "")
|
||||||
|
|
||||||
Snackbar.make(activity.window.decorView.findViewById(R.id.fam), "Pass moved to " + topic, Snackbar.LENGTH_LONG)
|
Snackbar.make(activity.window.decorView.findViewById(R.id.fam), "Pass moved to $topic", Snackbar.LENGTH_LONG)
|
||||||
.setAction(R.string.undo) { passClassifier.moveToTopic(pass, oldTopic) }
|
.setAction(R.string.undo) { passClassifier.moveToTopic(pass, oldTopic) }
|
||||||
.show()
|
.show()
|
||||||
passClassifier.moveToTopic(pass, topic)
|
passClassifier.moveToTopic(pass, topic)
|
||||||
|
|
|
@ -15,7 +15,7 @@ import java.io.FileNotFoundException
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val APP = "passandroid"
|
const val APP = "passandroid"
|
||||||
|
|
||||||
fun createAndAddEmptyPass(passStore: PassStore, resources: Resources): Pass {
|
fun createAndAddEmptyPass(passStore: PassStore, resources: Resources): Pass {
|
||||||
val pass = createBasePass()
|
val pass = createBasePass()
|
||||||
|
|
|
@ -40,7 +40,7 @@ class AndroidFileSystemPassStore(private val context: Context, settings: Setting
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
val of = com.squareup.moshi.JsonWriter.of(buffer)
|
val of = com.squareup.moshi.JsonWriter.of(buffer)
|
||||||
of.setIndent(" ")
|
of.indent = " "
|
||||||
jsonAdapter.toJson(of, pass as PassImpl)
|
jsonAdapter.toJson(of, pass as PassImpl)
|
||||||
buffer.close()
|
buffer.close()
|
||||||
of.close()
|
of.close()
|
||||||
|
@ -86,7 +86,7 @@ class AndroidFileSystemPassStore(private val context: Context, settings: Setting
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
save(result)
|
save(result)
|
||||||
}
|
}
|
||||||
passMap.put(id, result)
|
passMap[id] = result
|
||||||
notifyChange()
|
notifyChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ligi.passandroid.model
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.support.v7.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.R.string.preference_key_autolight
|
import org.ligi.passandroid.R.string.preference_key_autolight
|
||||||
import org.ligi.passandroid.R.string.preference_key_condensed
|
import org.ligi.passandroid.R.string.preference_key_condensed
|
||||||
|
@ -11,12 +11,12 @@ import java.io.File
|
||||||
|
|
||||||
class AndroidSettings(val context: Context) : Settings {
|
class AndroidSettings(val context: Context) : Settings {
|
||||||
|
|
||||||
internal val sharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(context) }
|
private val sharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(context) }
|
||||||
|
|
||||||
override fun getSortOrder(): PassSortOrder {
|
override fun getSortOrder(): PassSortOrder {
|
||||||
val key = context.getString(R.string.preference_key_sort)
|
val key = context.getString(R.string.preference_key_sort)
|
||||||
val stringValue = sharedPreferences.getString(key, "0")
|
val stringValue = sharedPreferences.getString(key, "0")
|
||||||
val id = Integer.valueOf(stringValue)!!
|
val id = Integer.valueOf(stringValue!!)
|
||||||
|
|
||||||
return PassSortOrder.values().first { it.int == id }
|
return PassSortOrder.values().first { it.int == id }
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class ApplePassbookQuirkCorrector(val tracker: Tracker) {
|
||||||
tryToFindDate(pass)
|
tryToFindDate(pass)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryToFindDate(pass: PassImpl) {
|
private fun tryToFindDate(pass: PassImpl) {
|
||||||
|
|
||||||
if (pass.calendarTimespan == null) {
|
if (pass.calendarTimespan == null) {
|
||||||
val foundDate = pass.fields.filter { "date" == it.key }.map {
|
val foundDate = pass.fields.filter { "date" == it.key }.map {
|
||||||
|
@ -44,11 +44,11 @@ class ApplePassbookQuirkCorrector(val tracker: Tracker) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPassFieldForKey(pass: PassImpl, key: String): PassField? {
|
private fun getPassFieldForKey(pass: PassImpl, key: String): PassField? {
|
||||||
return pass.fields.firstOrNull() { it.key != null && it.key == key }
|
return pass.fields.firstOrNull { it.key != null && it.key == key }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPassFieldThatMatchesLabel(pass: PassImpl, matcher: String): PassField? {
|
private fun getPassFieldThatMatchesLabel(pass: PassImpl, matcher: String): PassField? {
|
||||||
return pass.fields.firstOrNull() {
|
return pass.fields.firstOrNull {
|
||||||
val label = it.label
|
val label = it.label
|
||||||
label != null && label.matches(matcher.toRegex())
|
label != null && label.matches(matcher.toRegex())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package org.ligi.passandroid.model;
|
package org.ligi.passandroid.model;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import com.ibm.icu.text.CharsetDetector;
|
import com.ibm.icu.text.CharsetDetector;
|
||||||
import com.ibm.icu.text.CharsetMatch;
|
import com.ibm.icu.text.CharsetMatch;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
@ -12,7 +12,6 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.ligi.passandroid.App;
|
import org.ligi.passandroid.App;
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public class AppleStylePassTranslation extends HashMap<String, String> {
|
public class AppleStylePassTranslation extends HashMap<String, String> {
|
||||||
|
|
||||||
public String translate(String key) {
|
public String translate(String key) {
|
||||||
|
@ -63,6 +62,7 @@ public class AppleStylePassTranslation extends HashMap<String, String> {
|
||||||
if (fileData[0] == (byte) 0xEF && fileData[1] == (byte) 0xBB && fileData[2] == (byte) 0xBF) {
|
if (fileData[0] == (byte) 0xEF && fileData[1] == (byte) 0xBB && fileData[2] == (byte) 0xBF) {
|
||||||
final byte[] crop = new byte[fileData.length - 3];
|
final byte[] crop = new byte[fileData.length - 3];
|
||||||
System.arraycopy(fileData, 3, crop, 0, crop.length);
|
System.arraycopy(fileData, 3, crop, 0, crop.length);
|
||||||
|
//noinspection CharsetObjectCanBeUsed
|
||||||
return new String(crop, "utf-8");
|
return new String(crop, "utf-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ open class PassClassifier(val topicByIdMap: MutableMap<String, String>, private
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveToTopic(pass: Pass, newTopic: String) {
|
fun moveToTopic(pass: Pass, newTopic: String) {
|
||||||
topicByIdMap.put(pass.id, newTopic)
|
topicByIdMap[pass.id] = newTopic
|
||||||
|
|
||||||
processDataChange()
|
processDataChange()
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ open class PassClassifier(val topicByIdMap: MutableMap<String, String>, private
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPassListByTopic(topic: String): List<Pass> {
|
fun getPassListByTopic(topic: String): List<Pass> {
|
||||||
return topicByIdMap.filter { it.value.equals(topic) }.map { passStore.getPassbookForId(it.key) }.filterNotNull()
|
return topicByIdMap.filter { it.value == topic }.map { passStore.getPassbookForId(it.key) }.filterNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTopic(pass: Pass, default: String): String {
|
fun getTopic(pass: Pass, default: String): String {
|
||||||
|
@ -38,7 +38,7 @@ open class PassClassifier(val topicByIdMap: MutableMap<String, String>, private
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!default.isEmpty()) {
|
if (!default.isEmpty()) {
|
||||||
topicByIdMap.put(id, default)
|
topicByIdMap[id] = default
|
||||||
processDataChange()
|
processDataChange()
|
||||||
}
|
}
|
||||||
return default
|
return default
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.ligi.passandroid.model.comparator.PassSortOrder
|
||||||
import org.ligi.passandroid.model.pass.Pass
|
import org.ligi.passandroid.model.pass.Pass
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class PassStoreProjection(private val passStore: PassStore, val topic: String, private val passSortOrder: PassSortOrder? = null) {
|
class PassStoreProjection(private val passStore: PassStore, private val topic: String, private val passSortOrder: PassSortOrder? = null) {
|
||||||
|
|
||||||
var passList: List<Pass> = ArrayList()
|
var passList: List<Pass> = ArrayList()
|
||||||
private set
|
private set
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
package org.ligi.passandroid.model
|
package org.ligi.passandroid.model
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
|
||||||
import org.ligi.passandroid.Tracker
|
import org.ligi.passandroid.Tracker
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class PastLocationsStore constructor(private val sharedPreferences: SharedPreferences, private val tracker: Tracker) {
|
class PastLocationsStore constructor(private val sharedPreferences: SharedPreferences, private val tracker: Tracker) {
|
||||||
|
|
||||||
fun putLocation(path: String) {
|
fun putLocation(path: String) {
|
||||||
if (Build.VERSION.SDK_INT < 11) {
|
|
||||||
// feature not available for these versions
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val pastLocations = sharedPreferences.getStringSet(KEY_PAST_LOCATIONS, HashSet<String>())
|
val pastLocations = sharedPreferences.getStringSet(KEY_PAST_LOCATIONS, HashSet<String>())
|
||||||
|
|
||||||
if (pastLocations!!.size >= MAX_ELEMENTS) {
|
if (pastLocations!!.size >= MAX_ELEMENTS) {
|
||||||
|
@ -39,17 +33,11 @@ class PastLocationsStore constructor(private val sharedPreferences: SharedPrefer
|
||||||
|
|
||||||
// feature not available for these versions
|
// feature not available for these versions
|
||||||
val locations: Set<String>
|
val locations: Set<String>
|
||||||
@TargetApi(11)
|
get() = sharedPreferences.getStringSet(KEY_PAST_LOCATIONS, emptySet<String>())
|
||||||
get() {
|
|
||||||
if (Build.VERSION.SDK_INT < 11) {
|
|
||||||
return HashSet()
|
|
||||||
}
|
|
||||||
return sharedPreferences.getStringSet(KEY_PAST_LOCATIONS, HashSet<String>())
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val KEY_PAST_LOCATIONS = "past_locations"
|
const val KEY_PAST_LOCATIONS = "past_locations"
|
||||||
val MAX_ELEMENTS = 5
|
const val MAX_ELEMENTS = 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ class DirectionAwarePassByTimeComparator(private val direction: Int) : PassByTim
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DIRECTION_DESC = -1
|
const val DIRECTION_DESC = -1
|
||||||
val DIRECTION_ASC = 1
|
const val DIRECTION_ASC = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import java.util.*
|
||||||
open class PassByTimeComparator : Comparator<Pass> {
|
open class PassByTimeComparator : Comparator<Pass> {
|
||||||
|
|
||||||
override fun compare(lhs: Pass, rhs: Pass): Int {
|
override fun compare(lhs: Pass, rhs: Pass): Int {
|
||||||
return calculateCompareForNullValues(lhs, rhs, { leftDate: ZonedDateTime, rightDate: ZonedDateTime ->
|
return calculateCompareForNullValues(lhs, rhs) { leftDate: ZonedDateTime, rightDate: ZonedDateTime ->
|
||||||
return@calculateCompareForNullValues leftDate.compareTo(rightDate)
|
return@calculateCompareForNullValues leftDate.compareTo(rightDate)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun calculateCompareForNullValues(lhs: Pass, rhs: Pass, foo: (leftDate: ZonedDateTime, rightDate: ZonedDateTime) -> Int): Int {
|
protected fun calculateCompareForNullValues(lhs: Pass, rhs: Pass, foo: (leftDate: ZonedDateTime, rightDate: ZonedDateTime) -> Int): Int {
|
||||||
|
|
|
@ -11,10 +11,10 @@ class PassByTypeFirstAndTimeSecondComparator : Comparator<Pass> {
|
||||||
override fun compare(lhs: Pass, rhs: Pass): Int {
|
override fun compare(lhs: Pass, rhs: Pass): Int {
|
||||||
val compareResult = lhs.type.compareTo(rhs.type)
|
val compareResult = lhs.type.compareTo(rhs.type)
|
||||||
|
|
||||||
if (compareResult != 0) {
|
return if (compareResult != 0) {
|
||||||
return compareResult
|
compareResult
|
||||||
} else {
|
} else {
|
||||||
return passByTimeComparator.compare(lhs, rhs)
|
passByTimeComparator.compare(lhs, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,10 @@ enum class PassSortOrder constructor(val int: Int) {
|
||||||
TYPE(1),
|
TYPE(1),
|
||||||
DATE_DIFF(2);
|
DATE_DIFF(2);
|
||||||
|
|
||||||
fun toComparator(): Comparator<Pass> {
|
fun toComparator(): Comparator<Pass> = when (this) {
|
||||||
when (this) {
|
TYPE -> PassByTypeFirstAndTimeSecondComparator()
|
||||||
TYPE -> return PassByTypeFirstAndTimeSecondComparator()
|
DATE_DESC -> DirectionAwarePassByTimeComparator(DirectionAwarePassByTimeComparator.DIRECTION_DESC)
|
||||||
DATE_DESC -> return DirectionAwarePassByTimeComparator(DirectionAwarePassByTimeComparator.DIRECTION_DESC)
|
DATE_DIFF -> PassTemporalDistanceComparator()
|
||||||
DATE_DIFF -> return PassTemporalDistanceComparator()
|
DATE_ASC -> DirectionAwarePassByTimeComparator(DirectionAwarePassByTimeComparator.DIRECTION_ASC)
|
||||||
DATE_ASC -> return DirectionAwarePassByTimeComparator(DirectionAwarePassByTimeComparator.DIRECTION_ASC)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@ import org.threeten.bp.ZonedDateTime
|
||||||
class PassTemporalDistanceComparator : PassByTimeComparator() {
|
class PassTemporalDistanceComparator : PassByTimeComparator() {
|
||||||
|
|
||||||
override fun compare(lhs: Pass, rhs: Pass): Int {
|
override fun compare(lhs: Pass, rhs: Pass): Int {
|
||||||
return calculateCompareForNullValues(lhs, rhs, { leftDate: ZonedDateTime, rightDate: ZonedDateTime ->
|
return calculateCompareForNullValues(lhs, rhs) { leftDate: ZonedDateTime, rightDate: ZonedDateTime ->
|
||||||
val durationLeft = Duration.between(LocalDateTime.now(), leftDate).abs()
|
val durationLeft = Duration.between(LocalDateTime.now(), leftDate).abs()
|
||||||
val durationRight = Duration.between(LocalDateTime.now(), rightDate).abs()
|
val durationRight = Duration.between(LocalDateTime.now(), rightDate).abs()
|
||||||
|
|
||||||
return@calculateCompareForNullValues durationLeft.compareTo(durationRight)
|
return@calculateCompareForNullValues durationLeft.compareTo(durationRight)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.model.pass
|
package org.ligi.passandroid.model.pass
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.support.annotation.StringDef
|
import androidx.annotation.StringDef
|
||||||
import org.ligi.passandroid.model.PassBitmapDefinitions.*
|
import org.ligi.passandroid.model.PassBitmapDefinitions.*
|
||||||
import org.ligi.passandroid.model.PassStore
|
import org.ligi.passandroid.model.PassStore
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.model.pass
|
package org.ligi.passandroid.model.pass
|
||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.support.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
class PassField(var key: String?, var label: String?, var value: String?, var hide: Boolean) {
|
class PassField(var key: String?, var label: String?, var value: String?, var hide: Boolean) {
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,13 @@ class PassImpl(override val id: String) : Pass {
|
||||||
override var passIdent: String? = null
|
override var passIdent: String? = null
|
||||||
|
|
||||||
override fun getBitmap(passStore: PassStore, @Pass.PassBitmap passBitmap: String): Bitmap? {
|
override fun getBitmap(passStore: PassStore, @Pass.PassBitmap passBitmap: String): Bitmap? {
|
||||||
try {
|
return try {
|
||||||
val file = File(passStore.getPathForID(id), passBitmap + FILETYPE_IMAGES)
|
val file = File(passStore.getPathForID(id), passBitmap + FILETYPE_IMAGES)
|
||||||
return BitmapFactory.decodeStream(FileInputStream(file))
|
BitmapFactory.decodeStream(FileInputStream(file))
|
||||||
} catch (expectedInSomeCases_willJustReturnNull: FileNotFoundException) {
|
} catch (expectedInSomeCases_willJustReturnNull: FileNotFoundException) {
|
||||||
return null
|
null
|
||||||
} catch (e: OutOfMemoryError) {
|
} catch (e: OutOfMemoryError) {
|
||||||
return null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ class PassImpl(override val id: String) : Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val FILETYPE_IMAGES = ".png"
|
const val FILETYPE_IMAGES = ".png"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ class PassPrintDocumentAdapter(private val context: Context, private val pass: P
|
||||||
val centerPaint = Paint()
|
val centerPaint = Paint()
|
||||||
centerPaint.textAlign = Paint.Align.CENTER
|
centerPaint.textAlign = Paint.Align.CENTER
|
||||||
|
|
||||||
canvas.drawText(pass.description, canvas.width / 2f, centerPaint.textSize, centerPaint)
|
canvas.drawText(pass.description!!, canvas.width / 2f, centerPaint.textSize, centerPaint)
|
||||||
var currentBottom = centerPaint.textSize * 3
|
var currentBottom = centerPaint.textSize * 3
|
||||||
|
|
||||||
val barCode = pass.barCode
|
val barCode = pass.barCode
|
||||||
|
@ -83,14 +83,14 @@ class PassPrintDocumentAdapter(private val context: Context, private val pass: P
|
||||||
|
|
||||||
val destRect = Rect(0, 0, (bitmap.width * ratio).toInt(), (bitmap.height * ratio).toInt())
|
val destRect = Rect(0, 0, (bitmap.width * ratio).toInt(), (bitmap.height * ratio).toInt())
|
||||||
|
|
||||||
destRect.offset(((canvas.width - destRect.width()) / 2).toInt(), currentBottom.toInt())
|
destRect.offset((canvas.width - destRect.width()) / 2, currentBottom.toInt())
|
||||||
|
|
||||||
currentBottom += destRect.bottom
|
currentBottom += destRect.bottom
|
||||||
|
|
||||||
canvas.drawBitmap(bitmap, srcRect, destRect, centerPaint)
|
canvas.drawBitmap(bitmap, srcRect, destRect, centerPaint)
|
||||||
|
|
||||||
if (barCode.alternativeText != null) {
|
if (barCode.alternativeText != null) {
|
||||||
canvas.drawText(barCode.alternativeText, destRect.centerX().toFloat(), destRect.bottom.toFloat() + 7 + centerPaint.textSize, centerPaint)
|
canvas.drawText(barCode.alternativeText!!, destRect.centerX().toFloat(), destRect.bottom.toFloat() + 7 + centerPaint.textSize, centerPaint)
|
||||||
currentBottom += 7 + centerPaint.textSize * 2
|
currentBottom += 7 + centerPaint.textSize * 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,76 +32,76 @@ object AppleStylePassReader {
|
||||||
|
|
||||||
val pass = PassImpl(passFile.name)
|
val pass = PassImpl(passFile.name)
|
||||||
|
|
||||||
var pass_json: JSONObject? = null
|
var passJSON: JSONObject? = null
|
||||||
|
|
||||||
val localized_path = findLocalizedPath(passFile, language)
|
val localizedPath = findLocalizedPath(passFile, language)
|
||||||
|
|
||||||
if (localized_path != null) {
|
if (localizedPath != null) {
|
||||||
val file = File(localized_path, "pass.strings")
|
val file = File(localizedPath, "pass.strings")
|
||||||
translation.loadFromFile(file)
|
translation.loadFromFile(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
copyBitmapFile(passFile, localized_path, PassBitmapDefinitions.BITMAP_ICON)
|
copyBitmapFile(passFile, localizedPath, PassBitmapDefinitions.BITMAP_ICON)
|
||||||
copyBitmapFile(passFile, localized_path, PassBitmapDefinitions.BITMAP_LOGO)
|
copyBitmapFile(passFile, localizedPath, PassBitmapDefinitions.BITMAP_LOGO)
|
||||||
copyBitmapFile(passFile, localized_path, PassBitmapDefinitions.BITMAP_STRIP)
|
copyBitmapFile(passFile, localizedPath, PassBitmapDefinitions.BITMAP_STRIP)
|
||||||
copyBitmapFile(passFile, localized_path, PassBitmapDefinitions.BITMAP_THUMBNAIL)
|
copyBitmapFile(passFile, localizedPath, PassBitmapDefinitions.BITMAP_THUMBNAIL)
|
||||||
copyBitmapFile(passFile, localized_path, PassBitmapDefinitions.BITMAP_FOOTER)
|
copyBitmapFile(passFile, localizedPath, PassBitmapDefinitions.BITMAP_FOOTER)
|
||||||
|
|
||||||
val file = File(passFile, "pass.json")
|
val file = File(passFile, "pass.json")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val plainJsonString = AppleStylePassTranslation.readFileAsStringGuessEncoding(file)
|
val plainJsonString = AppleStylePassTranslation.readFileAsStringGuessEncoding(file)
|
||||||
pass_json = readJSONSafely(plainJsonString)
|
passJSON = readJSONSafely(plainJsonString)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.i("PassParse Exception " + e)
|
Log.i("PassParse Exception: $e")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json == null) {
|
if (passJSON == null) {
|
||||||
// I had got a strange passbook with UCS-2 which could not be parsed before
|
// I had got a strange passbook with UCS-2 which could not be parsed before
|
||||||
// was searching for a auto-detection, but could not find one with support for this encoding
|
// was searching for a auto-detection, but could not find one with support for this encoding
|
||||||
// and the right license
|
// and the right license
|
||||||
|
|
||||||
for (charset in Charset.availableCharsets().values) {
|
for (charset in Charset.availableCharsets().values) {
|
||||||
try {
|
try {
|
||||||
val json_str = file.bufferedReader(charset).readText()
|
val json = file.bufferedReader(charset).readText()
|
||||||
pass_json = readJSONSafely(json_str)
|
passJSON = readJSONSafely(json)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
// we try with next charset
|
// we try with next charset
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json != null) {
|
if (passJSON != null) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json == null) {
|
if (passJSON == null) {
|
||||||
Log.w("could not load pass.json from passcode ")
|
Log.w("could not load pass.json from passcode ")
|
||||||
App.tracker.trackEvent("problem_event", "pass", "without_pass_json", null)
|
App.tracker.trackEvent("problem_event", "pass", "without_pass_json", null)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val barcode_json = pass_json.getBarcodeJson()
|
val barcodeJSON = passJSON.getBarcodeJson()
|
||||||
if (barcode_json != null) {
|
if (barcodeJSON != null) {
|
||||||
val barcodeFormatString = barcode_json.getString("format")
|
val barcodeFormatString = barcodeJSON.getString("format")
|
||||||
|
|
||||||
App.tracker.trackEvent("measure_event", "barcode_format", barcodeFormatString, 0L)
|
App.tracker.trackEvent("measure_event", "barcode_format", barcodeFormatString, 0L)
|
||||||
val barcodeFormat = BarCode.getFormatFromString(barcodeFormatString)
|
val barcodeFormat = BarCode.getFormatFromString(barcodeFormatString)
|
||||||
val barCode = BarCode(barcodeFormat, barcode_json.getString("message"))
|
val barCode = BarCode(barcodeFormat, barcodeJSON.getString("message"))
|
||||||
pass.barCode = barCode
|
pass.barCode = barCode
|
||||||
|
|
||||||
if (barcode_json.has("altText")) {
|
if (barcodeJSON.has("altText")) {
|
||||||
pass.barCode!!.alternativeText = barcode_json.getString("altText")
|
pass.barCode!!.alternativeText = barcodeJSON.getString("altText")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO should check a bit more with barcode here - this can be dangerous
|
// TODO should check a bit more with barcode here - this can be dangerous
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json.has("relevantDate")) {
|
if (passJSON.has("relevantDate")) {
|
||||||
try {
|
try {
|
||||||
pass.calendarTimespan = PassImpl.TimeSpan(from = ZonedDateTime.parse(pass_json.getString("relevantDate")))
|
pass.calendarTimespan = PassImpl.TimeSpan(from = ZonedDateTime.parse(passJSON.getString("relevantDate")))
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
// be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here
|
// be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here
|
||||||
// OK then we just have no date here
|
// OK then we just have no date here
|
||||||
|
@ -112,9 +112,9 @@ object AppleStylePassReader {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json.has("expirationDate")) {
|
if (passJSON.has("expirationDate")) {
|
||||||
try {
|
try {
|
||||||
pass.validTimespans = listOf(PassImpl.TimeSpan(to = ZonedDateTime.parse(pass_json.getString("expirationDate"))))
|
pass.validTimespans = listOf(PassImpl.TimeSpan(to = ZonedDateTime.parse(passJSON.getString("expirationDate"))))
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
// be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here
|
// be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here
|
||||||
// OK then we just have no date here
|
// OK then we just have no date here
|
||||||
|
@ -125,17 +125,17 @@ object AppleStylePassReader {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pass.serial = readJsonSafeAsOptional(pass_json, "serialNumber")
|
pass.serial = readJsonSafeAsOptional(passJSON, "serialNumber")
|
||||||
pass.authToken = readJsonSafeAsOptional(pass_json, "authenticationToken")
|
pass.authToken = readJsonSafeAsOptional(passJSON, "authenticationToken")
|
||||||
pass.webServiceURL = readJsonSafeAsOptional(pass_json, "webServiceURL")
|
pass.webServiceURL = readJsonSafeAsOptional(passJSON, "webServiceURL")
|
||||||
pass.passIdent = readJsonSafeAsOptional(pass_json, "passTypeIdentifier")
|
pass.passIdent = readJsonSafeAsOptional(passJSON, "passTypeIdentifier")
|
||||||
|
|
||||||
val locations = ArrayList<PassLocation>()
|
val locations = ArrayList<PassLocation>()
|
||||||
try {
|
try {
|
||||||
|
|
||||||
val locations_json = pass_json.getJSONArray("locations")
|
val locationsJSON = passJSON.getJSONArray("locations")
|
||||||
for (i in 0..locations_json.length() - 1) {
|
for (i in 0 until locationsJSON.length()) {
|
||||||
val obj = locations_json.getJSONObject(i)
|
val obj = locationsJSON.getJSONObject(i)
|
||||||
|
|
||||||
val location = PassLocation()
|
val location = PassLocation()
|
||||||
location.lat = obj.getDouble("latitude")
|
location.lat = obj.getDouble("latitude")
|
||||||
|
@ -153,13 +153,13 @@ object AppleStylePassReader {
|
||||||
|
|
||||||
pass.locations = locations
|
pass.locations = locations
|
||||||
|
|
||||||
readJsonSafe(pass_json, "backgroundColor", object : JsonStringReadCallback {
|
readJsonSafe(passJSON, "backgroundColor", object : JsonStringReadCallback {
|
||||||
override fun onString(string: String) {
|
override fun onString(string: String) {
|
||||||
pass.accentColor = string.parseColor(Color.BLACK)
|
pass.accentColor = string.parseColor(Color.BLACK)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
readJsonSafe(pass_json, "description", object : JsonStringReadCallback {
|
readJsonSafe(passJSON, "description", object : JsonStringReadCallback {
|
||||||
override fun onString(string: String) {
|
override fun onString(string: String) {
|
||||||
pass.description = translation.translate(string)
|
pass.description = translation.translate(string)
|
||||||
}
|
}
|
||||||
|
@ -169,22 +169,22 @@ object AppleStylePassReader {
|
||||||
// try to find in a predefined set of tickets
|
// try to find in a predefined set of tickets
|
||||||
|
|
||||||
PassDefinitions.TYPE_TO_NAME.forEach {
|
PassDefinitions.TYPE_TO_NAME.forEach {
|
||||||
if (pass_json!!.has(it.value)) {
|
if (passJSON.has(it.value)) {
|
||||||
pass.type = it.key
|
pass.type = it.key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val type = PassDefinitions.TYPE_TO_NAME[pass.type]
|
val type = PassDefinitions.TYPE_TO_NAME[pass.type]
|
||||||
val type_json = pass_json.getJSONObject(type)
|
val typeJSON = passJSON.getJSONObject(type)
|
||||||
if (type_json != null) {
|
if (typeJSON != null) {
|
||||||
val fieldList: ArrayList<PassField> = ArrayList()
|
val fieldList: ArrayList<PassField> = ArrayList()
|
||||||
|
|
||||||
addFields(fieldList, type_json, "primaryFields", translation)
|
addFields(fieldList, typeJSON, "primaryFields", translation)
|
||||||
addFields(fieldList, type_json, "headerFields", translation)
|
addFields(fieldList, typeJSON, "headerFields", translation)
|
||||||
addFields(fieldList, type_json, "secondaryFields", translation)
|
addFields(fieldList, typeJSON, "secondaryFields", translation)
|
||||||
addFields(fieldList, type_json, "auxiliaryFields", translation)
|
addFields(fieldList, typeJSON, "auxiliaryFields", translation)
|
||||||
addFields(fieldList, type_json, "backFields", translation, hide = true)
|
addFields(fieldList, typeJSON, "backFields", translation, hide = true)
|
||||||
|
|
||||||
fieldList.add(PassField("", context.getString(R.string.type), context.getString(getHumanCategoryString(pass.type)), false))
|
fieldList.add(PassField("", context.getString(R.string.type), context.getString(getHumanCategoryString(pass.type)), false))
|
||||||
pass.fields = fieldList
|
pass.fields = fieldList
|
||||||
|
@ -195,7 +195,7 @@ object AppleStylePassReader {
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pass.creator = pass_json.getString("organizationName")
|
pass.creator = passJSON.getString("organizationName")
|
||||||
App.tracker.trackEvent("measure_event", "organisation_parse", pass.creator, 1L)
|
App.tracker.trackEvent("measure_event", "organisation_parse", pass.creator, 1L)
|
||||||
} catch (ignored: JSONException) {
|
} catch (ignored: JSONException) {
|
||||||
// ok - we have no organisation - big deal ..-)
|
// ok - we have no organisation - big deal ..-)
|
||||||
|
@ -220,7 +220,7 @@ object AppleStylePassReader {
|
||||||
private fun addFields(list: ArrayList<PassField>, type_json: JSONObject, fieldsName: String, translation: AppleStylePassTranslation, hide: Boolean = false) {
|
private fun addFields(list: ArrayList<PassField>, type_json: JSONObject, fieldsName: String, translation: AppleStylePassTranslation, hide: Boolean = false) {
|
||||||
try {
|
try {
|
||||||
val jsonArray = type_json.getJSONArray(fieldsName)
|
val jsonArray = type_json.getJSONArray(fieldsName)
|
||||||
for (i in 0..jsonArray.length() - 1) {
|
for (i in 0 until jsonArray.length()) {
|
||||||
try {
|
try {
|
||||||
val jsonObject = jsonArray.getJSONObject(i)
|
val jsonObject = jsonArray.getJSONObject(i)
|
||||||
val field = PassField(key = getField(jsonObject, "key", translation),
|
val field = PassField(key = getField(jsonObject, "key", translation),
|
||||||
|
@ -230,19 +230,18 @@ object AppleStylePassReader {
|
||||||
list.add(field)
|
list.add(field)
|
||||||
|
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
Log.w("could not process PassField from JSON for $fieldsName cause:$e")
|
Log.w("could not process PassField from JSON for $fieldsName cause: $e")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
Log.w("could not process PassFields $fieldsName from JSON$e")
|
Log.w("could not process PassFields $fieldsName from JSON: $e")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findLocalizedPath(path: File, language: String): String? {
|
private fun findLocalizedPath(path: File, language: String): String? {
|
||||||
|
val localized = File(path, "$language.lproj")
|
||||||
val localized = File(path, language + ".lproj")
|
|
||||||
|
|
||||||
if (localized.exists() && localized.isDirectory) {
|
if (localized.exists() && localized.isDirectory) {
|
||||||
App.tracker.trackEvent("measure_event", "pass", language + "_native_lproj", null)
|
App.tracker.trackEvent("measure_event", "pass", language + "_native_lproj", null)
|
||||||
|
@ -282,7 +281,6 @@ object AppleStylePassReader {
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
// some passes just do not have the field
|
// some passes just do not have the field
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +292,6 @@ object AppleStylePassReader {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +326,4 @@ object AppleStylePassReader {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,47 +21,47 @@ object PassReader {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val plainJsonString = file.bufferedReader().readText()
|
val plainJsonString = file.bufferedReader().readText()
|
||||||
val pass_json = readJSONSafely(plainJsonString)!!
|
val passJSON = readJSONSafely(plainJsonString)!!
|
||||||
|
|
||||||
if (pass_json.has("what")) {
|
if (passJSON.has("what")) {
|
||||||
val what_json = pass_json.getJSONObject("what")
|
val whatJSON = passJSON.getJSONObject("what")
|
||||||
pass.description = what_json.getString("description")
|
pass.description = whatJSON.getString("description")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json.has("meta")) {
|
if (passJSON.has("meta")) {
|
||||||
val meta_json = pass_json.getJSONObject("meta")
|
val metaJSON = passJSON.getJSONObject("meta")
|
||||||
pass.type = PassDefinitions.NAME_TO_TYPE[meta_json.getString("type")] ?: PassType.GENERIC
|
pass.type = PassDefinitions.NAME_TO_TYPE[metaJSON.getString("type")] ?: PassType.GENERIC
|
||||||
pass.creator = meta_json.getString("organisation")
|
pass.creator = metaJSON.getString("organisation")
|
||||||
pass.app = meta_json.getString("app")
|
pass.app = metaJSON.getString("app")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json.has("ui")) {
|
if (passJSON.has("ui")) {
|
||||||
val ui_json = pass_json.getJSONObject("ui")
|
val uiJSON = passJSON.getJSONObject("ui")
|
||||||
pass.accentColor = Color.parseColor(ui_json.getString("bgColor"))
|
pass.accentColor = Color.parseColor(uiJSON.getString("bgColor"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json.has("barcode")) {
|
if (passJSON.has("barcode")) {
|
||||||
val barcode_json = pass_json.getJSONObject("barcode")
|
val barcodeJSON = passJSON.getJSONObject("barcode")
|
||||||
val barcodeFormatString = barcode_json.getString("type")
|
val barcodeFormatString = barcodeJSON.getString("type")
|
||||||
|
|
||||||
val barcodeFormat = BarCode.getFormatFromString(barcodeFormatString)
|
val barcodeFormat = BarCode.getFormatFromString(barcodeFormatString)
|
||||||
val barCode = BarCode(barcodeFormat, barcode_json.getString("message"))
|
val barCode = BarCode(barcodeFormat, barcodeJSON.getString("message"))
|
||||||
pass.barCode = barCode
|
pass.barCode = barCode
|
||||||
|
|
||||||
if (barcode_json.has("altText")) {
|
if (barcodeJSON.has("altText")) {
|
||||||
barCode.alternativeText = barcode_json.getString("altText")
|
barCode.alternativeText = barcodeJSON.getString("altText")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass_json.has("when")) {
|
if (passJSON.has("when")) {
|
||||||
val dateTime = pass_json.getJSONObject("when").getString("dateTime")
|
val dateTime = passJSON.getJSONObject("when").getString("dateTime")
|
||||||
|
|
||||||
pass.calendarTimespan = PassImpl.TimeSpan()
|
pass.calendarTimespan = PassImpl.TimeSpan()
|
||||||
pass.calendarTimespan = PassImpl.TimeSpan(from = ZonedDateTime.parse(dateTime))
|
pass.calendarTimespan = PassImpl.TimeSpan(from = ZonedDateTime.parse(dateTime))
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.i("PassParse Exception " + e)
|
Log.i("PassParse Exception: $e")
|
||||||
}
|
}
|
||||||
|
|
||||||
return pass
|
return pass
|
||||||
|
|
|
@ -4,14 +4,15 @@ import android.app.Activity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.*
|
import android.view.View.*
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.android.synthetic.main.barcode.view.*
|
import kotlinx.android.synthetic.main.barcode.view.*
|
||||||
import org.ligi.kaxt.getSmallestSide
|
import org.ligi.kaxt.getSmallestSide
|
||||||
import org.ligi.passandroid.model.pass.BarCode
|
import org.ligi.passandroid.model.pass.BarCode
|
||||||
|
|
||||||
internal class BarcodeUIController(val rootView: View, private val barCode: BarCode?, activity: Activity, private val passViewHelper: PassViewHelper) {
|
internal class BarcodeUIController(private val rootView: View, private val barCode: BarCode?, activity: Activity, private val passViewHelper: PassViewHelper) {
|
||||||
|
|
||||||
fun getBarcodeView() = rootView.barcode_img
|
fun getBarcodeView(): ImageView = rootView.barcode_img
|
||||||
|
|
||||||
private var currentBarcodeWidth: Int = 0
|
private var currentBarcodeWidth: Int = 0
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,12 @@ class ExtractURLAsIphoneActivity : PassAndroidActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
progressDialog.show()
|
if (intent?.data != null) {
|
||||||
tracker.trackEvent("quirk_fix", "unpack_attempt", intent.data.host, null)
|
progressDialog.show()
|
||||||
|
tracker.trackEvent("quirk_fix", "unpack_attempt", intent?.data?.host, null)
|
||||||
|
|
||||||
DownloadExtractAndStartImportTask().execute()
|
DownloadExtractAndStartImportTask().execute()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class DownloadExtractAndStartImportTask : AsyncTask<Void, Void, String>() {
|
private inner class DownloadExtractAndStartImportTask : AsyncTask<Void, Void, String>() {
|
||||||
|
@ -34,7 +36,7 @@ class ExtractURLAsIphoneActivity : PassAndroidActivity() {
|
||||||
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
try {
|
try {
|
||||||
val requestBuilder = Request.Builder().url(URI(intent.data.toString()).toURL())
|
val requestBuilder = Request.Builder().url(URI(intent?.data.toString()).toURL())
|
||||||
requestBuilder.header("User-Agent", IPHONE_USER_AGENT)
|
requestBuilder.header("User-Agent", IPHONE_USER_AGENT)
|
||||||
|
|
||||||
val body = client.newCall(requestBuilder.build()).execute().body()
|
val body = client.newCall(requestBuilder.build()).execute().body()
|
||||||
|
@ -46,7 +48,7 @@ class ExtractURLAsIphoneActivity : PassAndroidActivity() {
|
||||||
val url = extractURL(bodyString) ?: return null
|
val url = extractURL(bodyString) ?: return null
|
||||||
|
|
||||||
if (!url.startsWith("http")) {
|
if (!url.startsWith("http")) {
|
||||||
return intent.data.scheme + "://" + intent.data.host + "/" + url
|
return intent?.data?.scheme + "://" + intent?.data?.host + "/" + url
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
|
@ -79,7 +81,7 @@ class ExtractURLAsIphoneActivity : PassAndroidActivity() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tracker.trackEvent("quirk_fix", "unpack_success", intent.data.host, null)
|
tracker.trackEvent("quirk_fix", "unpack_success", intent?.data?.host, null)
|
||||||
|
|
||||||
val intent = Intent(this@ExtractURLAsIphoneActivity, PassImportActivity::class.java)
|
val intent = Intent(this@ExtractURLAsIphoneActivity, PassImportActivity::class.java)
|
||||||
intent.data = Uri.parse(s)
|
intent.data = Uri.parse(s)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
@ -15,12 +16,19 @@ class FullscreenBarcodeActivity : PassViewActivityBase() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.fullscreen_image)
|
setContentView(R.layout.fullscreen_image)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 27) {
|
||||||
|
setShowWhenLocked(true)
|
||||||
|
setTurnScreenOn(true)
|
||||||
|
} else {
|
||||||
|
this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
if (currentPass == null || currentPass.barCode == null) {
|
if (currentPass.barCode == null) {
|
||||||
Log.w("FullscreenBarcodeActivity in bad state")
|
Log.w("FullscreenBarcodeActivity in bad state")
|
||||||
finish() // this should never happen, but better safe than sorry
|
finish() // this should never happen, but better safe than sorry
|
||||||
return
|
return
|
||||||
|
@ -47,7 +55,6 @@ class FullscreenBarcodeActivity : PassViewActivityBase() {
|
||||||
* ( reverse orientation / sensor is the problem here ..)
|
* ( reverse orientation / sensor is the problem here ..)
|
||||||
*/
|
*/
|
||||||
private fun setBestFittingOrientationForBarCode() {
|
private fun setBestFittingOrientationForBarCode() {
|
||||||
|
|
||||||
if (currentPass.barCode!!.format!!.isQuadratic()) {
|
if (currentPass.barCode!!.format!!.isQuadratic()) {
|
||||||
when (requestedOrientation) {
|
when (requestedOrientation) {
|
||||||
|
|
||||||
|
@ -72,9 +79,4 @@ class FullscreenBarcodeActivity : PassViewActivityBase() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
@ -26,16 +26,18 @@ internal class MoveToNewTopicUI(private val context: Activity, private val passS
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
val newTopicEditText = dialog.findViewById(R.id.new_topic_edit) as EditText
|
val newTopicEditText = dialog.findViewById<EditText>(R.id.new_topic_edit)
|
||||||
val suggestionButtonContainer= dialog.findViewById(R.id.topic_suggestions_button_container) as ViewGroup
|
val suggestionButtonContainer = dialog.findViewById<ViewGroup>(R.id.topic_suggestions_button_container)
|
||||||
|
|
||||||
// we need to do this here so the dialog does not get dismissed
|
if (newTopicEditText != null) {
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
// we need to do this here so the dialog does not get dismissed
|
||||||
if (newTopicEditText.text.toString().isEmpty()) {
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||||
newTopicEditText.error = context.getString(R.string.cannot_be_empty)
|
if (newTopicEditText.text.toString().isEmpty()) {
|
||||||
newTopicEditText.requestFocus()
|
newTopicEditText.error = context.getString(R.string.cannot_be_empty)
|
||||||
} else {
|
newTopicEditText.requestFocus()
|
||||||
move(newTopicEditText.text.toString())
|
} else {
|
||||||
|
move(newTopicEditText.text.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +45,12 @@ internal class MoveToNewTopicUI(private val context: Activity, private val passS
|
||||||
|
|
||||||
val suggestionTopicStringIds = intArrayOf(R.string.topic_trash, R.string.topic_archive, R.string.topic_new)
|
val suggestionTopicStringIds = intArrayOf(R.string.topic_trash, R.string.topic_archive, R.string.topic_new)
|
||||||
|
|
||||||
suggestionTopicStringIds.map { context.getString(it) }.forEach {
|
suggestionTopicStringIds.map { context.getString(it) }.forEach { topic ->
|
||||||
if (it != oldTopic) {
|
if (topic != oldTopic) {
|
||||||
val button = Button(context)
|
val button = Button(context)
|
||||||
button.text = it
|
button.text = topic
|
||||||
suggestionButtonContainer.addView(button)
|
suggestionButtonContainer?.addView(button)
|
||||||
button.setOnClickListener { _ -> move(it) }
|
button.setOnClickListener { move(topic) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,32 +2,36 @@ package org.ligi.passandroid.ui;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.support.design.widget.AppBarLayout;
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
import android.support.design.widget.CoordinatorLayout;
|
|
||||||
import android.support.design.widget.Snackbar;
|
import androidx.annotation.NonNull;
|
||||||
import android.support.v4.view.ViewCompat;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import net.i2p.android.ext.floatingactionbutton.FloatingActionsMenu;
|
import net.i2p.android.ext.floatingactionbutton.FloatingActionsMenu;
|
||||||
import org.ligi.passandroid.R;
|
import org.ligi.passandroid.R;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class MyShyFABBehavior extends CoordinatorLayout.Behavior<FloatingActionsMenu> {
|
public class MyShyFABBehavior extends CoordinatorLayout.Behavior<FloatingActionsMenu> {
|
||||||
|
|
||||||
public MyShyFABBehavior() {
|
public MyShyFABBehavior() {}
|
||||||
}
|
|
||||||
|
|
||||||
public MyShyFABBehavior(Context context, AttributeSet attrs) {
|
public MyShyFABBehavior(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionsMenu child, View dependency) {
|
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent,
|
||||||
|
@NonNull FloatingActionsMenu child,
|
||||||
|
@NonNull View dependency) {
|
||||||
return dependency instanceof Snackbar.SnackbarLayout || dependency instanceof AppBarLayout;
|
return dependency instanceof Snackbar.SnackbarLayout || dependency instanceof AppBarLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionsMenu child, View dependency) {
|
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent,
|
||||||
|
@NonNull FloatingActionsMenu child,
|
||||||
|
@NonNull View dependency) {
|
||||||
if (dependency instanceof Snackbar.SnackbarLayout) {
|
if (dependency instanceof Snackbar.SnackbarLayout) {
|
||||||
updateFabTranslationForSnackbar(child, dependency);
|
updateFabTranslationForSnackbar(child, dependency);
|
||||||
}
|
}
|
||||||
|
@ -40,23 +44,24 @@ public class MyShyFABBehavior extends CoordinatorLayout.Behavior<FloatingActions
|
||||||
} else {
|
} else {
|
||||||
distanceToScroll = (int) (child.getContext().getResources().getDimension(R.dimen.fab_size_normal) + 2 * fabBottomMargin);
|
distanceToScroll = (int) (child.getContext().getResources().getDimension(R.dimen.fab_size_normal) + 2 * fabBottomMargin);
|
||||||
}
|
}
|
||||||
final float ratio = ViewCompat.getY(dependency) / getToolbarHeight(dependency.getContext());
|
final float ratio = dependency.getY() / getToolbarHeight(dependency.getContext());
|
||||||
|
|
||||||
ViewCompat.setTranslationY(child, -distanceToScroll * ratio);
|
child.setTranslationY(-distanceToScroll * ratio);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDependentViewRemoved(final CoordinatorLayout parent, final FloatingActionsMenu child, final View dependency) {
|
public void onDependentViewRemoved(@NonNull final CoordinatorLayout parent,
|
||||||
|
@NonNull final FloatingActionsMenu child,
|
||||||
|
@NonNull final View dependency) {
|
||||||
super.onDependentViewRemoved(parent, child, dependency);
|
super.onDependentViewRemoved(parent, child, dependency);
|
||||||
onDependentViewChanged(parent,child,dependency);
|
onDependentViewChanged(parent,child,dependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFabTranslationForSnackbar(FloatingActionsMenu child, View dependency) {
|
private void updateFabTranslationForSnackbar(FloatingActionsMenu child, View dependency) {
|
||||||
final float translationY = ViewCompat.getTranslationY(dependency) - dependency.getHeight();
|
final float translationY = dependency.getTranslationY() - dependency.getHeight();
|
||||||
final float translationYClipped = Math.min(0, translationY);
|
child.setTranslationY(Math.min(0, translationY));
|
||||||
ViewCompat.setTranslationY(child, translationYClipped);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getToolbarHeight(Context context) {
|
private int getToolbarHeight(Context context) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import android.app.Activity
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.model.pass.Pass
|
import org.ligi.passandroid.model.pass.Pass
|
||||||
import org.ligi.passandroid.model.pass.PassLocation
|
import org.ligi.passandroid.model.pass.PassLocation
|
||||||
|
@ -15,25 +15,26 @@ import java.net.URLEncoder
|
||||||
fun Activity.showNavigateToLocationsDialog(pass: Pass, finishOnDone: Boolean) {
|
fun Activity.showNavigateToLocationsDialog(pass: Pass, finishOnDone: Boolean) {
|
||||||
val locations = pass.locations
|
val locations = pass.locations
|
||||||
|
|
||||||
if (locations.isEmpty()) {
|
when {
|
||||||
done(this, finishOnDone)
|
locations.isEmpty() -> done(this, finishOnDone)
|
||||||
} else if (locations.size == 1) {
|
locations.size == 1 -> {
|
||||||
startIntentForLocation(this, locations.first(), pass)
|
startIntentForLocation(this, locations.first(), pass)
|
||||||
done(this, finishOnDone)
|
done(this, finishOnDone)
|
||||||
} else if (locations.size > 1) {
|
|
||||||
val locationDescriptions = arrayOfNulls<String>(locations.size)
|
|
||||||
|
|
||||||
var i = 0
|
|
||||||
for (loc in locations) {
|
|
||||||
locationDescriptions[i++] = loc.getNameWithFallback(pass)
|
|
||||||
}
|
}
|
||||||
AlertDialog.Builder(this).setTitle(this.getString(R.string.choose_location))
|
locations.size > 1 -> {
|
||||||
.setItems(locationDescriptions) { _, which ->
|
val locationDescriptions = arrayOfNulls<String>(locations.size)
|
||||||
startIntentForLocation(this, locations[which], pass)
|
|
||||||
done(this, finishOnDone)
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
for (loc in locations) {
|
||||||
|
locationDescriptions[i++] = loc.getNameWithFallback(pass)
|
||||||
|
}
|
||||||
|
AlertDialog.Builder(this).setTitle(this.getString(R.string.choose_location))
|
||||||
|
.setItems(locationDescriptions) { _, which ->
|
||||||
|
startIntentForLocation(this, locations[which], pass)
|
||||||
|
done(this, finishOnDone)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.support.design.widget.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.support.v7.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
|
@ -26,12 +26,11 @@ class PassAdapter(private val passListActivity: AppCompatActivity, private val p
|
||||||
val inflater = LayoutInflater.from(viewGroup.context)
|
val inflater = LayoutInflater.from(viewGroup.context)
|
||||||
|
|
||||||
val res = inflater.inflate(R.layout.pass_list_item, viewGroup, false) as CardView
|
val res = inflater.inflate(R.layout.pass_list_item, viewGroup, false) as CardView
|
||||||
if (settings.isCondensedModeEnabled()) {
|
return if (settings.isCondensedModeEnabled()) {
|
||||||
return CondensedPassViewHolder(res)
|
CondensedPassViewHolder(res)
|
||||||
} else {
|
} else {
|
||||||
return VerbosePassViewHolder(res)
|
VerbosePassViewHolder(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: PassViewHolder, position: Int) {
|
override fun onBindViewHolder(viewHolder: PassViewHolder, position: Int) {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.ligi.kaxt.recreateWhenPossible
|
|
||||||
import org.ligi.passandroid.App
|
import org.ligi.passandroid.App
|
||||||
import org.ligi.passandroid.Tracker
|
import org.ligi.passandroid.Tracker
|
||||||
import org.ligi.passandroid.model.PassStore
|
import org.ligi.passandroid.model.PassStore
|
||||||
|
@ -22,7 +21,7 @@ open class PassAndroidActivity : AppCompatActivity() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
if (lastSetNightMode != null && lastSetNightMode != settings.getNightMode()) {
|
if (lastSetNightMode != null && lastSetNightMode != settings.getNightMode()) {
|
||||||
recreateWhenPossible()
|
recreate()
|
||||||
}
|
}
|
||||||
lastSetNightMode = settings.getNightMode()
|
lastSetNightMode = settings.getNightMode()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,12 @@ package org.ligi.passandroid.ui
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import kotlinx.android.synthetic.main.edit.*
|
import kotlinx.android.synthetic.main.edit.*
|
||||||
|
@ -58,7 +59,7 @@ class PassEditActivity : AppCompatActivity() {
|
||||||
when (i) {
|
when (i) {
|
||||||
0 -> showCategoryPickDialog(this@PassEditActivity, currentPass, bus)
|
0 -> showCategoryPickDialog(this@PassEditActivity, currentPass, bus)
|
||||||
1 -> showColorPickDialog(this@PassEditActivity, currentPass, bus)
|
1 -> showColorPickDialog(this@PassEditActivity, currentPass, bus)
|
||||||
2 -> PassEditActivityPermissionsDispatcher.pickImageWithCheck(this@PassEditActivity, ImageEditHelper.REQ_CODE_PICK_ICON)
|
2 -> pickImageWithPermissionCheck(ImageEditHelper.REQ_CODE_PICK_ICON)
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
@ -103,7 +104,7 @@ class PassEditActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
PassEditActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults)
|
onRequestPermissionsResult(requestCode, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refresh(pass: Pass) {
|
private fun refresh(pass: Pass) {
|
||||||
|
@ -126,14 +127,14 @@ class PassEditActivity : AppCompatActivity() {
|
||||||
|
|
||||||
val bitmap = currentPass.getBitmap(passStore, imageString)
|
val bitmap = currentPass.getBitmap(passStore, imageString)
|
||||||
|
|
||||||
val addButton = findViewById(add_logo)!!
|
val addButton = findViewById<Button>(add_logo)!!
|
||||||
addButton.visibility = if (bitmap == null) View.VISIBLE else View.GONE
|
addButton.visibility = if (bitmap == null) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
val listener = View.OnClickListener {
|
val listener = View.OnClickListener {
|
||||||
PassEditActivityPermissionsDispatcher.pickImageWithCheck(this@PassEditActivity, requestCode)
|
pickImageWithPermissionCheck(requestCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
val logoImage = findViewById(logo_img) as ImageView
|
val logoImage = findViewById<ImageView>(logo_img)
|
||||||
passViewHelper.setBitmapSafe(logoImage, bitmap)
|
passViewHelper.setBitmapSafe(logoImage, bitmap)
|
||||||
logoImage.setOnClickListener(listener)
|
logoImage.setOnClickListener(listener)
|
||||||
addButton.setOnClickListener(listener)
|
addButton.setOnClickListener(listener)
|
||||||
|
@ -159,7 +160,5 @@ class PassEditActivity : AppCompatActivity() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,35 +4,35 @@ import android.app.Activity
|
||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.support.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import android.support.v4.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import org.ligi.passandroid.App
|
import org.ligi.passandroid.App
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal open class PassExportTaskAndShare(protected val activity: Activity, val inputPath: File) {
|
internal open class PassExportTaskAndShare(protected val activity: Activity, private val inputPath: File) {
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
fun execute() {
|
fun execute() {
|
||||||
val file = File(activity.filesDir, "share/share.espass") // important - the FileProvider must be configured for this path
|
val file = File(activity.filesDir, "share/share.espass") // important - the FileProvider must be configured for this path
|
||||||
val passExporter = PassExporter(inputPath, file)
|
val passExporter = PassExporter(inputPath, file)
|
||||||
val progress_dialog = ProgressDialog(activity)
|
val progressDialog = ProgressDialog(activity)
|
||||||
progress_dialog.setTitle(R.string.preparing_pass)
|
progressDialog.setTitle(R.string.preparing_pass)
|
||||||
progress_dialog.setMessage(activity.getString(R.string.please_wait))
|
progressDialog.setMessage(activity.getString(R.string.please_wait))
|
||||||
progress_dialog.show()
|
progressDialog.show()
|
||||||
|
|
||||||
val handler = Handler()
|
val handler = Handler()
|
||||||
Thread(Runnable {
|
Thread(Runnable {
|
||||||
passExporter.export()
|
passExporter.export()
|
||||||
handler.post {
|
handler.post {
|
||||||
if (!activity.isFinishing && progress_dialog.isShowing) {
|
if (!activity.isFinishing && progressDialog.isShowing) {
|
||||||
progress_dialog.dismiss()
|
progressDialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passExporter.exception != null) {
|
if (passExporter.exception != null) {
|
||||||
App.tracker.trackException("passExporterException", passExporter.exception, false)
|
App.tracker.trackException("passExporterException", passExporter.exception!!, false)
|
||||||
Toast.makeText(activity, "could not export pass " + passExporter.exception, Toast.LENGTH_LONG).show()
|
Toast.makeText(activity, "could not export pass: " + passExporter.exception, Toast.LENGTH_LONG).show()
|
||||||
} else {
|
} else {
|
||||||
val uriForFile = FileProvider.getUriForFile(activity, activity.getString(R.string.authority_fileprovider), file)
|
val uriForFile = FileProvider.getUriForFile(activity, activity.getString(R.string.authority_fileprovider), file)
|
||||||
val it = Intent(Intent.ACTION_SEND)
|
val it = Intent(Intent.ACTION_SEND)
|
||||||
|
|
|
@ -2,9 +2,8 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import org.ligi.kaxt.dismissIfShowing
|
import org.ligi.kaxt.dismissIfShowing
|
||||||
import org.ligi.kaxt.startActivityFromClass
|
import org.ligi.kaxt.startActivityFromClass
|
||||||
|
@ -44,22 +43,21 @@ class PassImportActivity : AppCompatActivity() {
|
||||||
|
|
||||||
progressDialog.show()
|
progressDialog.show()
|
||||||
|
|
||||||
doImport(false)
|
doImportWithPermissionCheck(false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
PassImportActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults)
|
onRequestPermissionsResult(requestCode, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
fun doImport(withPermission: Boolean) {
|
fun doImport(withPermission: Boolean) {
|
||||||
Thread({
|
Thread {
|
||||||
try {
|
try {
|
||||||
val fromURI = fromURI(this, intent.data)
|
val fromURI = fromURI(this, intent!!.data!!)
|
||||||
|
|
||||||
runOnUiThread({
|
runOnUiThread {
|
||||||
progressDialog.dismissIfShowing()
|
progressDialog.dismissIfShowing()
|
||||||
|
|
||||||
if (fromURI == null) {
|
if (fromURI == null) {
|
||||||
|
@ -87,25 +85,20 @@ class PassImportActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (e.message?.contains("Permission") == true && !withPermission) {
|
if (e.message?.contains("Permission") == true && !withPermission) {
|
||||||
PassImportActivityPermissionsDispatcher.doImportWithCheck(this@PassImportActivity, true)
|
doImportWithPermissionCheck(true)
|
||||||
} else {
|
} else {
|
||||||
tracker.trackException("Error in import", e, false)
|
tracker.trackException("Error in import", e, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}.start()
|
||||||
|
|
||||||
}).start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OnPermissionDenied(Manifest.permission.READ_EXTERNAL_STORAGE)
|
@OnPermissionDenied(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
fun showDeniedDialog() {
|
fun showDeniedDialog() {
|
||||||
progressDialog.dismissIfShowing()
|
progressDialog.dismissIfShowing()
|
||||||
alert(R.string.error_no_permission_msg, R.string.error_no_permission_title, onOKListener = DialogInterface.OnClickListener { _, _ -> finish() })
|
alert(R.string.error_no_permission_msg, R.string.error_no_permission_title, onOK = { finish() })
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.design.widget.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import android.support.v4.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import android.support.v4.view.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import android.support.v7.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -99,7 +99,7 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
PassListActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults)
|
onRequestPermissionsResult(requestCode, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(VERSION_STARTING_TO_SUPPORT_STORAGE_FRAMEWORK)
|
@TargetApi(VERSION_STARTING_TO_SUPPORT_STORAGE_FRAMEWORK)
|
||||||
|
@ -162,7 +162,7 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
|
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
State.lastSelectedTab = position
|
State.lastSelectedTab = position
|
||||||
supportInvalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
|
@ -189,7 +189,7 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fab_action_scan.setOnClickListener {
|
fab_action_scan.setOnClickListener {
|
||||||
PassListActivityPermissionsDispatcher.scanWithCheck(this)
|
scanWithPermissionCheck()
|
||||||
fam.collapse()
|
fam.collapse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,18 +214,21 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_emptytrash -> {
|
R.id.menu_emptytrash -> {
|
||||||
AlertDialog.Builder(this).setMessage(getString(R.string.empty_trash_dialog_message)).setIcon(R.drawable.ic_alert_warning).setTitle(getString(R.string.empty_trash_dialog_title)).setPositiveButton(R.string.emtytrash_label) { dialog, which ->
|
AlertDialog.Builder(this)
|
||||||
val passStoreProjection = PassStoreProjection(passStore,
|
.setMessage(getString(R.string.empty_trash_dialog_message))
|
||||||
getString(R.string.topic_trash),
|
.setIcon(R.drawable.ic_alert_warning)
|
||||||
null)
|
.setTitle(getString(R.string.empty_trash_dialog_title))
|
||||||
|
.setPositiveButton(R.string.emtytrash_label) { _, _ ->
|
||||||
|
val passStoreProjection = PassStoreProjection(passStore,
|
||||||
|
getString(R.string.topic_trash),
|
||||||
|
null)
|
||||||
|
|
||||||
for (pass in passStoreProjection.passList) {
|
for (pass in passStoreProjection.passList) {
|
||||||
passStore.deletePassWithId(pass.id)
|
passStore.deletePassWithId(pass.id)
|
||||||
}
|
}
|
||||||
}.setNegativeButton(android.R.string.cancel, null).show()
|
}.setNegativeButton(android.R.string.cancel, null).show()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item)
|
else -> drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +272,7 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
|
|
||||||
setupWithViewPagerIfNeeded()
|
setupWithViewPagerIfNeeded()
|
||||||
|
|
||||||
supportInvalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
val empty = passStore.classifier.topicByIdMap.isEmpty()
|
val empty = passStore.classifier.topicByIdMap.isEmpty()
|
||||||
emptyView.visibility = if (empty) View.VISIBLE else View.GONE
|
emptyView.visibility = if (empty) View.VISIBLE else View.GONE
|
||||||
|
@ -284,7 +287,6 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areTabLayoutAndViewPagerInSync(): Boolean {
|
private fun areTabLayoutAndViewPagerInSync(): Boolean {
|
||||||
|
|
||||||
if (adapter.count != tab_layout.tabCount) {
|
if (adapter.count != tab_layout.tabCount) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -296,7 +298,6 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
|
@ -306,5 +307,4 @@ class PassListActivity : PassAndroidActivity() {
|
||||||
else -> super.onBackPressed()
|
else -> super.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import android.support.v4.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper.*
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper.*
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -38,7 +39,7 @@ class PassListFragment : Fragment() {
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
val inflate = inflater.inflate(R.layout.pass_recycler, container, false)
|
val inflate = inflater.inflate(R.layout.pass_recycler, container, false)
|
||||||
|
|
||||||
passStoreProjection = PassStoreProjection(passStore, arguments.getString(BUNDLE_KEY_TOPIC)!!, settings.getSortOrder())
|
passStoreProjection = PassStoreProjection(passStore, arguments?.getString(BUNDLE_KEY_TOPIC)!!, settings.getSortOrder())
|
||||||
adapter = PassAdapter(activity as AppCompatActivity, passStoreProjection)
|
adapter = PassAdapter(activity as AppCompatActivity, passStoreProjection)
|
||||||
|
|
||||||
inflate.pass_recyclerview.adapter = adapter
|
inflate.pass_recyclerview.adapter = adapter
|
||||||
|
@ -47,10 +48,10 @@ class PassListFragment : Fragment() {
|
||||||
|
|
||||||
val simpleItemTouchCallback = object : SimpleCallback(0, LEFT or RIGHT) {
|
val simpleItemTouchCallback = object : SimpleCallback(0, LEFT or RIGHT) {
|
||||||
|
|
||||||
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder)
|
override fun onMove(recyclerView: RecyclerView, viewHolder: ViewHolder, target: ViewHolder)
|
||||||
= false
|
= false
|
||||||
|
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
|
override fun onSwiped(viewHolder: ViewHolder, swipeDir: Int) {
|
||||||
this@PassListFragment.onSwiped(viewHolder.adapterPosition, swipeDir)
|
this@PassListFragment.onSwiped(viewHolder.adapterPosition, swipeDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,10 +68,12 @@ class PassListFragment : Fragment() {
|
||||||
val pass = passStoreProjection.passList[pos]
|
val pass = passStoreProjection.passList[pos]
|
||||||
val nextTopic = passStore.classifier.getTopicWithOffset(pass, if (swipeDir == LEFT) -1 else 1)
|
val nextTopic = passStore.classifier.getTopicWithOffset(pass, if (swipeDir == LEFT) -1 else 1)
|
||||||
|
|
||||||
if (nextTopic != null) {
|
activity?.let {
|
||||||
moveWithUndoSnackbar(passStore.classifier, pass, nextTopic, activity)
|
if (nextTopic != null) {
|
||||||
} else {
|
moveWithUndoSnackbar(passStore.classifier, pass, nextTopic, it)
|
||||||
MoveToNewTopicUI(activity, passStore, pass).show()
|
} else {
|
||||||
|
MoveToNewTopicUI(it, passStore, pass).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,12 +96,12 @@ class PassListFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val BUNDLE_KEY_TOPIC = "topic"
|
||||||
private val BUNDLE_KEY_TOPIC = "topic"
|
|
||||||
|
|
||||||
fun newInstance(topic: String) = PassListFragment().apply {
|
fun newInstance(topic: String) = PassListFragment().apply {
|
||||||
arguments = Bundle()
|
val bundle = Bundle()
|
||||||
arguments.putString(BUNDLE_KEY_TOPIC, topic)
|
bundle.putString(BUNDLE_KEY_TOPIC, topic)
|
||||||
|
arguments = bundle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.support.v4.app.NavUtils
|
import androidx.core.app.NavUtils
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.design.widget.NavigationView
|
import com.google.android.material.navigation.NavigationView
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import kotlinx.android.synthetic.main.navigation_drawer_header.view.*
|
import kotlinx.android.synthetic.main.navigation_drawer_header.view.*
|
||||||
|
@ -20,9 +21,8 @@ class PassNavigationView(context: Context, attrs: AttributeSet) : NavigationView
|
||||||
val passStore: PassStore = App.kodein.instance()
|
val passStore: PassStore = App.kodein.instance()
|
||||||
val bus: EventBus = App.kodein.instance()
|
val bus: EventBus = App.kodein.instance()
|
||||||
|
|
||||||
fun getIntent(id: Int) = when (id) {
|
private fun getIntent(id: Int) = when (id) {
|
||||||
R.id.menu_settings -> Intent(context, PreferenceActivity::class.java)
|
R.id.menu_settings -> Intent(context, PreferenceActivity::class.java)
|
||||||
R.id.menu_plus -> intentFromUrl("https://plus.google.com/communities/116353894782342292067")
|
|
||||||
R.id.menu_github -> intentFromUrl("https://github.com/ligi/PassAndroid")
|
R.id.menu_github -> intentFromUrl("https://github.com/ligi/PassAndroid")
|
||||||
R.id.menu_beta -> intentFromUrl("https://play.google.com/apps/testing/org.ligi.passandroid")
|
R.id.menu_beta -> intentFromUrl("https://play.google.com/apps/testing/org.ligi.passandroid")
|
||||||
R.id.menu_language -> intentFromUrl("https://transifex.com/projects/p/passandroid")
|
R.id.menu_language -> intentFromUrl("https://transifex.com/projects/p/passandroid")
|
||||||
|
@ -33,8 +33,9 @@ class PassNavigationView(context: Context, attrs: AttributeSet) : NavigationView
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun intentFromUrl(url: String) = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) }
|
private fun intentFromUrl(url: String) = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) }
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi") // FIXME: temporary workaround for false-positive
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
super.onAttachedToWindow()
|
super.onAttachedToWindow()
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ class PassNavigationView(context: Context, attrs: AttributeSet) : NavigationView
|
||||||
onPassStoreChangeEvent(PassStoreChangeEvent)
|
onPassStoreChangeEvent(PassStoreChangeEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi") // FIXME: temporary workaround for false-positive
|
||||||
override fun onDetachedFromWindow() {
|
override fun onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow()
|
super.onDetachedFromWindow()
|
||||||
bus.unregister(this)
|
bus.unregister(this)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.support.v4.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import android.support.v4.app.FragmentStatePagerAdapter
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
import android.support.v4.view.PagerAdapter
|
import androidx.viewpager.widget.PagerAdapter
|
||||||
import org.ligi.passandroid.model.PassClassifier
|
import org.ligi.passandroid.model.PassClassifier
|
||||||
|
|
||||||
class PassTopicFragmentPagerAdapter(private val passClassifier: PassClassifier, fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
|
class PassTopicFragmentPagerAdapter(private val passClassifier: PassClassifier, fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
|
||||||
|
|
||||||
private lateinit var topic_array: Array<String>
|
private lateinit var topics: Array<String>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
@ -15,15 +15,16 @@ class PassTopicFragmentPagerAdapter(private val passClassifier: PassClassifier,
|
||||||
|
|
||||||
override fun notifyDataSetChanged() {
|
override fun notifyDataSetChanged() {
|
||||||
val topics = passClassifier.getTopics()
|
val topics = passClassifier.getTopics()
|
||||||
topic_array = topics.toTypedArray()
|
this.topics = topics.toTypedArray()
|
||||||
super.notifyDataSetChanged()
|
super.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItem(position: Int) = PassListFragment.newInstance(topic_array[position])
|
override fun getItem(position: Int) = PassListFragment.newInstance(topics[position])
|
||||||
|
|
||||||
override fun getItemPosition(`object`: Any?) = PagerAdapter.POSITION_NONE // TODO - return POSITION_UNCHANGED in some cases
|
// TODO - return POSITION_UNCHANGED in some cases
|
||||||
|
override fun getItemPosition(`object`: Any) = PagerAdapter.POSITION_NONE
|
||||||
|
|
||||||
override fun getCount() = topic_array.size
|
override fun getCount() = topics.size
|
||||||
|
|
||||||
override fun getPageTitle(position: Int) = topic_array[position]
|
override fun getPageTitle(position: Int) = topics[position]
|
||||||
}
|
}
|
|
@ -2,11 +2,14 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.*
|
import androidx.core.app.*
|
||||||
import android.support.v4.view.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
import kotlinx.android.synthetic.main.activity_pass_view_base.*
|
import kotlinx.android.synthetic.main.activity_pass_view_base.*
|
||||||
import org.ligi.kaxt.disableRotation
|
import org.ligi.kaxt.disableRotation
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
|
@ -20,6 +23,13 @@ class PassViewActivity : PassViewActivityBase() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 27) {
|
||||||
|
setShowWhenLocked(true)
|
||||||
|
setTurnScreenOn(true)
|
||||||
|
} else {
|
||||||
|
this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
||||||
|
}
|
||||||
|
|
||||||
disableRotation()
|
disableRotation()
|
||||||
setContentView(R.layout.activity_pass_view)
|
setContentView(R.layout.activity_pass_view)
|
||||||
|
|
||||||
|
@ -30,8 +40,8 @@ class PassViewActivity : PassViewActivityBase() {
|
||||||
viewPager.adapter = pagerAdapter
|
viewPager.adapter = pagerAdapter
|
||||||
viewPager.currentItem = pagerAdapter.getPos(currentPass)
|
viewPager.currentItem = pagerAdapter.getPos(currentPass)
|
||||||
viewPager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
viewPager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||||
override fun onPageSelected(i: Int) {
|
override fun onPageSelected(pos: Int) {
|
||||||
currentPass = pagerAdapter.getPass(i)
|
currentPass = pagerAdapter.getPass(pos)
|
||||||
passStore.currentPass = currentPass
|
passStore.currentPass = currentPass
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -95,18 +105,18 @@ class PassViewActivity : PassViewActivityBase() {
|
||||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
val upIntent = NavUtils.getParentActivityIntent(this)
|
val upIntent = NavUtils.getParentActivityIntent(this)
|
||||||
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
|
if (upIntent != null) {
|
||||||
TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities()
|
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
|
||||||
finish()
|
TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities()
|
||||||
} else {
|
finish()
|
||||||
NavUtils.navigateUpTo(this, upIntent)
|
} else {
|
||||||
|
NavUtils.navigateUpTo(this, upIntent)
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
true
|
else false
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() = window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,12 +5,15 @@ import android.app.Dialog
|
||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.ShortcutInfo
|
||||||
|
import android.content.pm.ShortcutManager
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.design.widget.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
@ -25,6 +28,7 @@ import org.ligi.passandroid.ui.UnzipPassController.InputStreamUnzipControllerSpe
|
||||||
import permissions.dispatcher.NeedsPermission
|
import permissions.dispatcher.NeedsPermission
|
||||||
import permissions.dispatcher.RuntimePermissions
|
import permissions.dispatcher.RuntimePermissions
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@SuppressLint("Registered")
|
@SuppressLint("Registered")
|
||||||
@RuntimePermissions
|
@RuntimePermissions
|
||||||
|
@ -44,10 +48,8 @@ open class PassViewActivityBase : PassAndroidActivity() {
|
||||||
try {
|
try {
|
||||||
val config = ViewConfiguration.get(this)
|
val config = ViewConfiguration.get(this)
|
||||||
val menuKeyField = ViewConfiguration::class.java.getDeclaredField("sHasPermanentMenuKey")
|
val menuKeyField = ViewConfiguration::class.java.getDeclaredField("sHasPermanentMenuKey")
|
||||||
if (menuKeyField != null) {
|
menuKeyField.isAccessible = true
|
||||||
menuKeyField.isAccessible = true
|
menuKeyField.setBoolean(config, false)
|
||||||
menuKeyField.setBoolean(config, false)
|
|
||||||
}
|
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
// Ignore - but at least we tried ;-)
|
// Ignore - but at least we tried ;-)
|
||||||
}
|
}
|
||||||
|
@ -82,7 +84,7 @@ open class PassViewActivityBase : PassAndroidActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passStore.currentPass == null) {
|
if (passStore.currentPass == null) {
|
||||||
tracker.trackException("pass not present in " + this, false)
|
tracker.trackException("pass not present in $this", false)
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -127,7 +129,7 @@ open class PassViewActivityBase : PassAndroidActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.install_shortcut -> {
|
R.id.install_shortcut -> {
|
||||||
PassViewActivityBasePermissionsDispatcher.createShortcutWithCheck(this)
|
createShortcutWithPermissionCheck()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,28 +145,39 @@ open class PassViewActivityBase : PassAndroidActivity() {
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
PassViewActivityBasePermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults)
|
onRequestPermissionsResult(requestCode, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
@NeedsPermission("com.android.launcher.permission.INSTALL_SHORTCUT")
|
@NeedsPermission("com.android.launcher.permission.INSTALL_SHORTCUT")
|
||||||
fun createShortcut() {
|
fun createShortcut() {
|
||||||
val intent = Intent("com.android.launcher.action.INSTALL_SHORTCUT")
|
|
||||||
val shortcutIntent = Intent()
|
val shortcutIntent = Intent()
|
||||||
shortcutIntent.putExtra(EXTRA_KEY_UUID, currentPass.id)
|
shortcutIntent.putExtra(EXTRA_KEY_UUID, currentPass.id)
|
||||||
val component = ComponentName(BuildConfig.APPLICATION_ID, BuildConfig.APPLICATION_ID + ".ui.PassViewActivity")
|
shortcutIntent.component = ComponentName(BuildConfig.APPLICATION_ID,
|
||||||
shortcutIntent.component = component
|
BuildConfig.APPLICATION_ID + ".ui.PassViewActivity")
|
||||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent)
|
|
||||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, currentPass.description)
|
|
||||||
|
|
||||||
val passBitmap = currentPass.getBitmap(passStore, BITMAP_ICON)
|
val passBitmap = currentPass.getBitmap(passStore, BITMAP_ICON)
|
||||||
|
val shortcutIcon = if (passBitmap != null) {
|
||||||
val bitmapToUse = if (passBitmap != null) {
|
|
||||||
Bitmap.createScaledBitmap(passBitmap, 128, 128, true)
|
Bitmap.createScaledBitmap(passBitmap, 128, 128, true)
|
||||||
} else {
|
} else {
|
||||||
BitmapFactory.decodeResource(resources, R.drawable.ic_launcher)
|
BitmapFactory.decodeResource(resources, R.drawable.ic_launcher)
|
||||||
}
|
}
|
||||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmapToUse)
|
|
||||||
sendBroadcast(intent)
|
if (Build.VERSION.SDK_INT >= 25) {
|
||||||
|
val shortcutManager = getSystemService<ShortcutManager>(ShortcutManager::class.java)
|
||||||
|
val shortcut = ShortcutInfo.Builder(this, "id1")
|
||||||
|
.setShortLabel(currentPass.description ?: "")
|
||||||
|
.setIcon(Icon.createWithBitmap(shortcutIcon))
|
||||||
|
.setIntent(shortcutIntent)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
shortcutManager.dynamicShortcuts = Arrays.asList(shortcut)
|
||||||
|
} else {
|
||||||
|
val intent = Intent("com.android.launcher.action.INSTALL_SHORTCUT")
|
||||||
|
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent)
|
||||||
|
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, currentPass.description)
|
||||||
|
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, shortcutIcon)
|
||||||
|
sendBroadcast(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class UpdateAsync : Runnable {
|
inner class UpdateAsync : Runnable {
|
||||||
|
@ -183,7 +196,7 @@ open class PassViewActivityBase : PassAndroidActivity() {
|
||||||
|
|
||||||
val url = pass.webServiceURL + "/v1/passes/" + pass.passIdent + "/" + pass.serial
|
val url = pass.webServiceURL + "/v1/passes/" + pass.passIdent + "/" + pass.serial
|
||||||
val requestBuilder = Request.Builder().url(url)
|
val requestBuilder = Request.Builder().url(url)
|
||||||
requestBuilder.addHeader("Authorization", "ApplePass " + pass.authToken!!)
|
requestBuilder.addHeader("Authorization", "ApplePass " + pass.authToken)
|
||||||
|
|
||||||
val request = requestBuilder.build()
|
val request = requestBuilder.build()
|
||||||
|
|
||||||
|
@ -250,7 +263,7 @@ open class PassViewActivityBase : PassAndroidActivity() {
|
||||||
params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL
|
params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL
|
||||||
win.attributes = params
|
win.attributes = params
|
||||||
fullBrightnessSet = true
|
fullBrightnessSet = true
|
||||||
supportInvalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -2,14 +2,15 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.support.v4.text.util.LinkifyCompat
|
import androidx.core.text.util.LinkifyCompat
|
||||||
import android.text.util.Linkify
|
import android.text.util.Linkify
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import kotlinx.android.synthetic.main.activity_pass_view.*
|
import kotlinx.android.synthetic.main.activity_pass_view.*
|
||||||
import kotlinx.android.synthetic.main.barcode.*
|
import kotlinx.android.synthetic.main.barcode.*
|
||||||
|
@ -27,7 +28,7 @@ import org.ligi.passandroid.ui.pass_view_holder.VerbosePassViewHolder
|
||||||
|
|
||||||
class PassViewFragment : Fragment() {
|
class PassViewFragment : Fragment() {
|
||||||
|
|
||||||
private val passViewHelper by lazy { PassViewHelper(activity) }
|
private val passViewHelper by lazy { PassViewHelper(requireActivity()) }
|
||||||
private var passStore : PassStore = App.kodein.instance()
|
private var passStore : PassStore = App.kodein.instance()
|
||||||
lateinit var pass : Pass
|
lateinit var pass : Pass
|
||||||
|
|
||||||
|
@ -57,10 +58,10 @@ class PassViewFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
barcode_img.setOnClickListener {
|
barcode_img.setOnClickListener {
|
||||||
activity.startActivityFromClass(FullscreenBarcodeActivity::class.java)
|
activity?.startActivityFromClass(FullscreenBarcodeActivity::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
BarcodeUIController(view!!, pass.barCode, activity, passViewHelper)
|
BarcodeUIController(view!!, pass.barCode, activity!!, passViewHelper)
|
||||||
|
|
||||||
processImage(logo_img_view, PassBitmapDefinitions.BITMAP_LOGO, pass)
|
processImage(logo_img_view, PassBitmapDefinitions.BITMAP_LOGO, pass)
|
||||||
processImage(footer_img_view, PassBitmapDefinitions.BITMAP_FOOTER, pass)
|
processImage(footer_img_view, PassBitmapDefinitions.BITMAP_FOOTER, pass)
|
||||||
|
@ -68,7 +69,7 @@ class PassViewFragment : Fragment() {
|
||||||
processImage(strip_img_view, PassBitmapDefinitions.BITMAP_STRIP, pass)
|
processImage(strip_img_view, PassBitmapDefinitions.BITMAP_STRIP, pass)
|
||||||
|
|
||||||
if (map_container != null) {
|
if (map_container != null) {
|
||||||
if (!(pass.locations.isNotEmpty() && PassbookMapsFacade.init(activity))) {
|
if (!(pass.locations.isNotEmpty() && PassbookMapsFacade.init(activity as FragmentActivity))) {
|
||||||
@Suppress("PLUGIN_WARNING")
|
@Suppress("PLUGIN_WARNING")
|
||||||
map_container.visibility = View.GONE
|
map_container.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
@ -82,15 +83,15 @@ class PassViewFragment : Fragment() {
|
||||||
if (field.hide) {
|
if (field.hide) {
|
||||||
backStrBuilder.append(field.toHtmlSnippet())
|
backStrBuilder.append(field.toHtmlSnippet())
|
||||||
} else {
|
} else {
|
||||||
val v = activity.layoutInflater.inflate(R.layout.main_field_item, front_field_container, false)
|
val v = activity!!.layoutInflater.inflate(R.layout.main_field_item, front_field_container, false)
|
||||||
val key = v.findViewById(R.id.key) as TextView
|
val key = v?.findViewById<TextView>(R.id.key)
|
||||||
key.text = field.label
|
key?.text = field.label
|
||||||
val value = v.findViewById(R.id.value) as TextView
|
val value = v?.findViewById<TextView>(R.id.value)
|
||||||
value.text = field.value
|
value?.text = field.value
|
||||||
|
|
||||||
front_field_container.addView(v)
|
front_field_container.addView(v)
|
||||||
LinkifyCompat.addLinks(key, Linkify.ALL)
|
key?.let { LinkifyCompat.addLinks(it, Linkify.ALL) }
|
||||||
LinkifyCompat.addLinks(value, Linkify.ALL)
|
value?.let { LinkifyCompat.addLinks(it, Linkify.ALL) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +105,7 @@ class PassViewFragment : Fragment() {
|
||||||
LinkifyCompat.addLinks(back_fields, Linkify.ALL)
|
LinkifyCompat.addLinks(back_fields, Linkify.ALL)
|
||||||
|
|
||||||
val passViewHolder = VerbosePassViewHolder(pass_card)
|
val passViewHolder = VerbosePassViewHolder(pass_card)
|
||||||
passViewHolder.apply(pass, passStore, activity)
|
passViewHolder.apply(pass, passStore, activity!!)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
@ -114,7 +114,6 @@ class PassViewFragment : Fragment() {
|
||||||
val rootView = inflater.inflate(R.layout.activity_pass_view_page, container, false)
|
val rootView = inflater.inflate(R.layout.activity_pass_view_page, container, false)
|
||||||
arguments?.takeIf { it.containsKey(PassViewActivityBase.EXTRA_KEY_UUID) }?.apply {
|
arguments?.takeIf { it.containsKey(PassViewActivityBase.EXTRA_KEY_UUID) }?.apply {
|
||||||
val uuid = getString(PassViewActivityBase.EXTRA_KEY_UUID)
|
val uuid = getString(PassViewActivityBase.EXTRA_KEY_UUID)
|
||||||
|
|
||||||
pass = if (uuid != null) {
|
pass = if (uuid != null) {
|
||||||
passStore.getPassbookForId(uuid) ?: passStore.currentPass!!
|
passStore.getPassbookForId(uuid) ?: passStore.currentPass!!
|
||||||
} else {
|
} else {
|
||||||
|
@ -125,10 +124,10 @@ class PassViewFragment : Fragment() {
|
||||||
return rootView
|
return rootView
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
val passExtrasView = activity.layoutInflater.inflate(R.layout.pass_view_extra_data, passExtrasContainer, false)
|
val passExtrasView = activity!!.layoutInflater.inflate(R.layout.pass_view_extra_data, passExtrasContainer, false)
|
||||||
passExtrasContainer.addView(passExtrasView)
|
passExtrasContainer.addView(passExtrasView)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,13 +17,13 @@ class PassViewHelper(private val context: Activity) {
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
imageView.setImageBitmap(bitmap)
|
imageView.setImageBitmap(bitmap)
|
||||||
imageView.visibility = View.VISIBLE
|
imageView.visibility = View.VISIBLE
|
||||||
imageView.layoutParams = getLayoutParamsSoThatWeHaveMinimumAFingerInHeight(imageView, bitmap)
|
imageView.layoutParams = getLayoutParamsMinHeight(imageView, bitmap)
|
||||||
} else {
|
} else {
|
||||||
imageView.visibility = View.GONE
|
imageView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLayoutParamsSoThatWeHaveMinimumAFingerInHeight(imageView: ImageView, bitmap: Bitmap)
|
private fun getLayoutParamsMinHeight(imageView: ImageView, bitmap: Bitmap)
|
||||||
= imageView.layoutParams!!.apply {
|
= imageView.layoutParams!!.apply {
|
||||||
height = if (bitmap.height < fingerSize) {
|
height = if (bitmap.height < fingerSize) {
|
||||||
fingerSize
|
fingerSize
|
||||||
|
@ -33,5 +33,4 @@ class PassViewHelper(private val context: Activity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val windowWidth by lazy { context.windowManager.getSizeAsPointCompat().x }
|
val windowWidth by lazy { context.windowManager.getSizeAsPointCompat().x }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,9 @@ package org.ligi.passandroid.ui
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import android.support.v7.app.AppCompatDelegate.MODE_NIGHT_AUTO
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO
|
||||||
import android.support.v7.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import org.ligi.kaxt.recreateWhenPossible
|
|
||||||
import org.ligi.passandroid.App
|
import org.ligi.passandroid.App
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import permissions.dispatcher.NeedsPermission
|
import permissions.dispatcher.NeedsPermission
|
||||||
|
@ -27,15 +26,14 @@ class PrefsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPref
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||||
if (key == getString(R.string.preference_key_nightmode)) {
|
if (key == getString(R.string.preference_key_nightmode)) {
|
||||||
|
|
||||||
@AppCompatDelegate.NightMode val nightMode = App.settings.getNightMode()
|
@AppCompatDelegate.NightMode val nightMode = App.settings.getNightMode()
|
||||||
|
|
||||||
if (nightMode == MODE_NIGHT_AUTO) {
|
if (nightMode == MODE_NIGHT_AUTO) {
|
||||||
PrefsFragmentPermissionsDispatcher.ensureDayNightWithCheck(this)
|
ensureDayNightWithPermissionCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(nightMode)
|
AppCompatDelegate.setDefaultNightMode(nightMode)
|
||||||
activity.recreateWhenPossible()
|
activity?.recreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +49,7 @@ class PrefsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPref
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
PrefsFragmentPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults)
|
onRequestPermissionsResult(requestCode, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.support.v4.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.ligi.passandroid.App
|
import org.ligi.passandroid.App
|
||||||
|
@ -57,7 +57,7 @@ class SearchPassesIntentService : IntentService("SearchPassesIntentService") {
|
||||||
|
|
||||||
val preferences = PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
val preferences = PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
||||||
for (path in PastLocationsStore(preferences, tracker).locations) {
|
for (path in PastLocationsStore(preferences, tracker).locations) {
|
||||||
search_in(File(path), false)
|
searchIn(File(path), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// note to future_me: yea one thinks we only need to search root here, but root was /system for me and so
|
// note to future_me: yea one thinks we only need to search root here, but root was /system for me and so
|
||||||
|
@ -69,19 +69,19 @@ class SearchPassesIntentService : IntentService("SearchPassesIntentService") {
|
||||||
// up the refreshing of passes as it took so long to traverse all files on the SDCard
|
// up the refreshing of passes as it took so long to traverse all files on the SDCard
|
||||||
// one could think about not going there anymore but a short look at this showed that it seems cost more time to check than what it gains
|
// one could think about not going there anymore but a short look at this showed that it seems cost more time to check than what it gains
|
||||||
// in download there are mostly single files in a flat dir - no huge tree behind this imho
|
// in download there are mostly single files in a flat dir - no huge tree behind this imho
|
||||||
search_in(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), true)
|
searchIn(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), true)
|
||||||
|
|
||||||
// | /system
|
// | /system
|
||||||
search_in(Environment.getRootDirectory(), true)
|
searchIn(Environment.getRootDirectory(), true)
|
||||||
|
|
||||||
// | /mnt/sdcard
|
// | /mnt/sdcard
|
||||||
search_in(Environment.getExternalStorageDirectory(), true)
|
searchIn(Environment.getExternalStorageDirectory(), true)
|
||||||
|
|
||||||
// | /cache
|
// | /cache
|
||||||
search_in(Environment.getDownloadCacheDirectory(), true)
|
searchIn(Environment.getDownloadCacheDirectory(), true)
|
||||||
|
|
||||||
// | /data
|
// | /data
|
||||||
search_in(Environment.getDataDirectory(), true)
|
searchIn(Environment.getDataDirectory(), true)
|
||||||
notifyManager!!.cancel(PROGRESS_NOTIFICATION_ID)
|
notifyManager!!.cancel(PROGRESS_NOTIFICATION_ID)
|
||||||
|
|
||||||
bus.post(ScanFinishedEvent(foundList!!))
|
bus.post(ScanFinishedEvent(foundList!!))
|
||||||
|
@ -90,7 +90,7 @@ class SearchPassesIntentService : IntentService("SearchPassesIntentService") {
|
||||||
/**
|
/**
|
||||||
* recursive voyage starting at path to find files named .pkpass
|
* recursive voyage starting at path to find files named .pkpass
|
||||||
*/
|
*/
|
||||||
private fun search_in(path: File, recursive: Boolean) {
|
private fun searchIn(path: File, recursive: Boolean) {
|
||||||
|
|
||||||
if (System.currentTimeMillis() - lastProgressUpdate > 1000) {
|
if (System.currentTimeMillis() - lastProgressUpdate > 1000) {
|
||||||
lastProgressUpdate = System.currentTimeMillis()
|
lastProgressUpdate = System.currentTimeMillis()
|
||||||
|
@ -114,7 +114,7 @@ class SearchPassesIntentService : IntentService("SearchPassesIntentService") {
|
||||||
}
|
}
|
||||||
Log.i("search " + file.absoluteFile)
|
Log.i("search " + file.absoluteFile)
|
||||||
if (recursive && file.isDirectory) {
|
if (recursive && file.isDirectory) {
|
||||||
search_in(file, true)
|
searchIn(file, true)
|
||||||
} else if (file.name.toLowerCase().endsWith(".pkpass") || file.name.toLowerCase().endsWith(".espass")) {
|
} else if (file.name.toLowerCase().endsWith(".pkpass") || file.name.toLowerCase().endsWith(".espass")) {
|
||||||
Log.i("found" + file.absolutePath)
|
Log.i("found" + file.absolutePath)
|
||||||
|
|
||||||
|
@ -149,10 +149,8 @@ class SearchPassesIntentService : IntentService("SearchPassesIntentService") {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val PROGRESS_NOTIFICATION_ID = 1
|
||||||
val PROGRESS_NOTIFICATION_ID = 1
|
const val FOUND_NOTIFICATION_ID = 2
|
||||||
val FOUND_NOTIFICATION_ID = 2
|
const val REQUEST_CODE = 1
|
||||||
|
|
||||||
val REQUEST_CODE = 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.support.v4.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.model.PassBitmapDefinitions
|
import org.ligi.passandroid.model.PassBitmapDefinitions
|
||||||
import org.ligi.passandroid.model.PassStore
|
import org.ligi.passandroid.model.PassStore
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui
|
package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import com.github.salomonbrys.kodein.instance
|
import com.github.salomonbrys.kodein.instance
|
||||||
import com.ortiz.touch.TouchImageView
|
import com.ortiz.touch.TouchImageView
|
||||||
|
|
|
@ -39,7 +39,7 @@ object UnzipPassController {
|
||||||
tempFile.delete()
|
tempFile.delete()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
App.tracker.trackException("problem processing InputStream", e, false)
|
App.tracker.trackException("problem processing InputStream", e, false)
|
||||||
spec.failCallback?.fail("problem with temp file" + e)
|
spec.failCallback?.fail("problem with temp file: $e")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,12 @@ object UnzipPassController {
|
||||||
private fun processFile(spec: FileUnzipControllerSpec) {
|
private fun processFile(spec: FileUnzipControllerSpec) {
|
||||||
|
|
||||||
var uuid = UUID.randomUUID().toString()
|
var uuid = UUID.randomUUID().toString()
|
||||||
val path = File(spec.context.cacheDir, "temp/" + uuid)
|
val path = File(spec.context.cacheDir, "temp/$uuid")
|
||||||
|
|
||||||
path.mkdirs()
|
path.mkdirs()
|
||||||
|
|
||||||
if (!path.exists()) {
|
if (!path.exists()) {
|
||||||
spec.failCallback?.fail("Problem creating the temp dir: " + path)
|
spec.failCallback?.fail("Problem creating the temp dir: $path")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,94 +66,89 @@ object UnzipPassController {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val manifest_json: JSONObject
|
|
||||||
val manifestFile = File(path, "manifest.json")
|
val manifestFile = File(path, "manifest.json")
|
||||||
val espassFile = File(path, "main.json")
|
val espassFile = File(path, "main.json")
|
||||||
|
val manifestJSON: JSONObject
|
||||||
|
|
||||||
if (manifestFile.exists()) {
|
when {
|
||||||
try {
|
manifestFile.exists() -> try {
|
||||||
val readToString = manifestFile.bufferedReader().readText()
|
val readToString = manifestFile.bufferedReader().readText()
|
||||||
manifest_json = readJSONSafely(readToString)!!
|
manifestJSON = readJSONSafely(readToString)!!
|
||||||
uuid = manifest_json.getString("pass.json")
|
uuid = manifestJSON.getString("pass.json")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
spec.failCallback?.fail("Problem with manifest.json: " + e)
|
spec.failCallback?.fail("Problem with manifest.json: $e")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
espassFile.exists() -> try {
|
||||||
} else if (espassFile.exists()) {
|
|
||||||
try {
|
|
||||||
val readToString = espassFile.bufferedReader().readText()
|
val readToString = espassFile.bufferedReader().readText()
|
||||||
manifest_json = readJSONSafely(readToString)!!
|
manifestJSON = readJSONSafely(readToString)!!
|
||||||
uuid = manifest_json.getString("id")
|
uuid = manifestJSON.getString("id")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
spec.failCallback?.fail("Problem with manifest.json: " + e)
|
spec.failCallback?.fail("Problem with manifest.json: $e")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
|
val bitmap = BitmapFactory.decodeFile(spec.zipFileString)
|
||||||
|
val resources = spec.context.resources
|
||||||
|
|
||||||
} else {
|
if (bitmap != null) {
|
||||||
|
val imagePass = createPassForImageImport(resources)
|
||||||
|
val pathForID = spec.passStore.getPathForID(imagePass.id)
|
||||||
|
pathForID.mkdirs()
|
||||||
|
|
||||||
|
File(spec.zipFileString).copyTo(File(pathForID, "strip.png"))
|
||||||
|
|
||||||
val bitmap = BitmapFactory.decodeFile(spec.zipFileString)
|
spec.passStore.save(imagePass)
|
||||||
|
spec.passStore.classifier.moveToTopic(imagePass, "new")
|
||||||
val resources = spec.context.resources
|
spec.onSuccessCallback?.call(imagePass.id)
|
||||||
if (bitmap != null) {
|
return
|
||||||
val imagePass = createPassForImageImport(resources)
|
|
||||||
val pathForID = spec.passStore.getPathForID(imagePass.id)
|
|
||||||
pathForID.mkdirs()
|
|
||||||
|
|
||||||
File(spec.zipFileString).copyTo(File(pathForID, "strip.png"))
|
|
||||||
|
|
||||||
spec.passStore.save(imagePass)
|
|
||||||
spec.passStore.classifier.moveToTopic(imagePass, "new")
|
|
||||||
spec.onSuccessCallback?.call(imagePass.id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
try {
|
|
||||||
val file = File(spec.zipFileString)
|
|
||||||
val readUtf8 = Okio.buffer(Okio.source(file)).readUtf8(4)
|
|
||||||
if (readUtf8 == "%PDF") {
|
|
||||||
val open = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
|
|
||||||
val pdfRenderer = PdfRenderer(open)
|
|
||||||
|
|
||||||
val page = pdfRenderer.openPage(0)
|
|
||||||
val ratio = page.height.toFloat() / page.width
|
|
||||||
|
|
||||||
val widthPixels = resources.displayMetrics.widthPixels
|
|
||||||
val createBitmap = Bitmap.createBitmap(widthPixels, (widthPixels * ratio).toInt(), Bitmap.Config.ARGB_8888)
|
|
||||||
page.render(createBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
|
||||||
|
|
||||||
val imagePass = createPassForPDFImport(resources)
|
|
||||||
val pathForID = spec.passStore.getPathForID(imagePass.id)
|
|
||||||
pathForID.mkdirs()
|
|
||||||
|
|
||||||
createBitmap.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(File(pathForID, "strip.png")))
|
|
||||||
|
|
||||||
spec.passStore.save(imagePass)
|
|
||||||
spec.passStore.classifier.moveToTopic(imagePass, "new")
|
|
||||||
spec.onSuccessCallback?.call(imagePass.id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
try {
|
||||||
|
val file = File(spec.zipFileString)
|
||||||
|
val readUtf8 = Okio.buffer(Okio.source(file)).readUtf8(4)
|
||||||
|
if (readUtf8 == "%PDF") {
|
||||||
|
val open = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
|
||||||
|
val pdfRenderer = PdfRenderer(open)
|
||||||
|
|
||||||
spec.failCallback?.fail("Pass is not espass or pkpass format :-(")
|
val page = pdfRenderer.openPage(0)
|
||||||
return
|
val ratio = page.height.toFloat() / page.width
|
||||||
|
|
||||||
|
val widthPixels = resources.displayMetrics.widthPixels
|
||||||
|
val createBitmap = Bitmap.createBitmap(widthPixels, (widthPixels * ratio).toInt(), Bitmap.Config.ARGB_8888)
|
||||||
|
page.render(createBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
||||||
|
|
||||||
|
val imagePass = createPassForPDFImport(resources)
|
||||||
|
val pathForID = spec.passStore.getPathForID(imagePass.id)
|
||||||
|
pathForID.mkdirs()
|
||||||
|
|
||||||
|
createBitmap.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(File(pathForID, "strip.png")))
|
||||||
|
|
||||||
|
spec.passStore.save(imagePass)
|
||||||
|
spec.passStore.classifier.moveToTopic(imagePass, "new")
|
||||||
|
spec.onSuccessCallback?.call(imagePass.id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.failCallback?.fail("Pass is not espass or pkpass format :-(")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec.targetPath.mkdirs()
|
spec.targetPath.mkdirs()
|
||||||
val rename_file = File(spec.targetPath, uuid)
|
val renamedFile = File(spec.targetPath, uuid)
|
||||||
|
|
||||||
if (spec.overwrite && rename_file.exists()) {
|
if (spec.overwrite && renamedFile.exists()) {
|
||||||
rename_file.deleteRecursively()
|
renamedFile.deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rename_file.exists()) {
|
if (!renamedFile.exists()) {
|
||||||
path.renameTo(rename_file)
|
path.renameTo(renamedFile)
|
||||||
} else {
|
} else {
|
||||||
Log.i("Pass with same ID exists")
|
Log.i("Pass with same ID exists")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ligi.passandroid.ui
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
import org.ligi.passandroid.model.InputStreamWithSource
|
import org.ligi.passandroid.model.InputStreamWithSource
|
||||||
import org.ligi.passandroid.model.PassStore
|
import org.ligi.passandroid.model.PassStore
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ligi.passandroid.ui;
|
package org.ligi.passandroid.ui;
|
||||||
|
|
||||||
import android.support.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
|
|
|
@ -8,8 +8,8 @@ import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import android.support.v7.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -90,6 +90,7 @@ import java.util.Map;
|
||||||
* @author Brad Drehmer
|
* @author Brad Drehmer
|
||||||
* @author gcstang
|
* @author gcstang
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class BarCodeIntentIntegrator {
|
public class BarCodeIntentIntegrator {
|
||||||
|
|
||||||
public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
|
public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
|
||||||
|
@ -130,7 +131,7 @@ public class BarCodeIntentIntegrator {
|
||||||
private String buttonYes;
|
private String buttonYes;
|
||||||
private String buttonNo;
|
private String buttonNo;
|
||||||
private List<String> targetApplications;
|
private List<String> targetApplications;
|
||||||
private final Map<String, Object> moreExtras = new HashMap<String, Object>(3);
|
private final Map<String, Object> moreExtras = new HashMap<>(3);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param activity {@link Activity} invoking the integration
|
* @param activity {@link Activity} invoking the integration
|
||||||
|
@ -313,7 +314,7 @@ public class BarCodeIntentIntegrator {
|
||||||
* @see android.app.Activity#startActivityForResult(Intent, int)
|
* @see android.app.Activity#startActivityForResult(Intent, int)
|
||||||
* @see android.app.Fragment#startActivityForResult(Intent, int)
|
* @see android.app.Fragment#startActivityForResult(Intent, int)
|
||||||
*/
|
*/
|
||||||
protected void startActivityForResult(Intent intent, int code) {
|
private void startActivityForResult(Intent intent, @SuppressWarnings("SameParameterValue") int code) {
|
||||||
if (fragment == null) {
|
if (fragment == null) {
|
||||||
activity.startActivityForResult(intent, code);
|
activity.startActivityForResult(intent, code);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package org.ligi.passandroid.ui.edit
|
package org.ligi.passandroid.ui.edit
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.support.v4.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
import kotlinx.android.synthetic.main.barcode_edit.view.*
|
import kotlinx.android.synthetic.main.barcode_edit.view.*
|
||||||
|
@ -14,14 +14,11 @@ import org.ligi.passandroid.ui.BarcodeUIController
|
||||||
import org.ligi.passandroid.ui.PassViewHelper
|
import org.ligi.passandroid.ui.PassViewHelper
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class BarcodeEditController(val rootView: View, internal val context: AppCompatActivity, barCode: BarCode) {
|
class BarcodeEditController(private val rootView: View, internal val context: AppCompatActivity, barCode: BarCode) {
|
||||||
|
private var barcodeFormat: PassBarCodeFormat?
|
||||||
var barcodeFormat: PassBarCodeFormat?
|
private val intentFragment: Fragment
|
||||||
|
|
||||||
internal val intentFragment: Fragment
|
|
||||||
|
|
||||||
class IntentFragment : Fragment() {
|
class IntentFragment : Fragment() {
|
||||||
|
|
||||||
var scanCallback: (String) -> Unit = {}
|
var scanCallback: (String) -> Unit = {}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
@ -37,7 +34,7 @@ class BarcodeEditController(val rootView: View, internal val context: AppCompatA
|
||||||
rootView.barcodeRadioGroup.addView(radioButton)
|
rootView.barcodeRadioGroup.addView(radioButton)
|
||||||
|
|
||||||
radioButton.text = it.name
|
radioButton.text = it.name
|
||||||
radioButton.setOnCheckedChangeListener { buttonView, isChecked ->
|
radioButton.setOnCheckedChangeListener { _, isChecked ->
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
barcodeFormat = it
|
barcodeFormat = it
|
||||||
refresh()
|
refresh()
|
||||||
|
@ -53,7 +50,7 @@ class BarcodeEditController(val rootView: View, internal val context: AppCompatA
|
||||||
intentFragment = IntentFragment()
|
intentFragment = IntentFragment()
|
||||||
barcodeFormat = barCode.format
|
barcodeFormat = barCode.format
|
||||||
|
|
||||||
rootView.randomButton.setOnClickListener({
|
rootView.randomButton.setOnClickListener {
|
||||||
rootView.messageInput.setText(when (barcodeFormat) {
|
rootView.messageInput.setText(when (barcodeFormat) {
|
||||||
EAN_8 -> getRandomEAN8()
|
EAN_8 -> getRandomEAN8()
|
||||||
EAN_13 -> getRandomEAN13()
|
EAN_13 -> getRandomEAN13()
|
||||||
|
@ -61,9 +58,9 @@ class BarcodeEditController(val rootView: View, internal val context: AppCompatA
|
||||||
else -> UUID.randomUUID().toString().toUpperCase()
|
else -> UUID.randomUUID().toString().toUpperCase()
|
||||||
})
|
})
|
||||||
refresh()
|
refresh()
|
||||||
})
|
}
|
||||||
|
|
||||||
rootView.scanButton.setOnClickListener({
|
rootView.scanButton.setOnClickListener {
|
||||||
val barCodeIntentIntegrator = BarCodeIntentIntegrator(intentFragment)
|
val barCodeIntentIntegrator = BarCodeIntentIntegrator(intentFragment)
|
||||||
|
|
||||||
if (barcodeFormat == QR_CODE) {
|
if (barcodeFormat == QR_CODE) {
|
||||||
|
@ -72,7 +69,7 @@ class BarcodeEditController(val rootView: View, internal val context: AppCompatA
|
||||||
barCodeIntentIntegrator.initiateScan(setOf(barcodeFormat!!.name))
|
barCodeIntentIntegrator.initiateScan(setOf(barcodeFormat!!.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
}
|
||||||
|
|
||||||
intentFragment.scanCallback = { newMessage ->
|
intentFragment.scanCallback = { newMessage ->
|
||||||
rootView.messageInput.setText(newMessage)
|
rootView.messageInput.setText(newMessage)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui.edit
|
package org.ligi.passandroid.ui.edit
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -26,7 +26,7 @@ class FieldsEditFragment : Fragment() {
|
||||||
this.inflater = inflater
|
this.inflater = inflater
|
||||||
val inflate = inflater.inflate(R.layout.edit_fields, container, false)
|
val inflate = inflater.inflate(R.layout.edit_fields, container, false)
|
||||||
|
|
||||||
isEditingHiddenFields = arguments.getBoolean(ARGUMENT_KEY)
|
arguments?.let { isEditingHiddenFields = it.getBoolean(ARGUMENT_KEY) }
|
||||||
|
|
||||||
if (isEditingHiddenFields) {
|
if (isEditingHiddenFields) {
|
||||||
inflate.add_field.setText(R.string.add_back_fields)
|
inflate.add_field.setText(R.string.add_back_fields)
|
||||||
|
@ -74,7 +74,7 @@ class FieldsEditFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val ARGUMENT_KEY = "KEY"
|
private const val ARGUMENT_KEY = "KEY"
|
||||||
|
|
||||||
fun create(primary: Boolean): FieldsEditFragment {
|
fun create(primary: Boolean): FieldsEditFragment {
|
||||||
val fieldsEditFragment = FieldsEditFragment()
|
val fieldsEditFragment = FieldsEditFragment()
|
||||||
|
|
|
@ -46,12 +46,12 @@ class ImageEditHelper(private val context: Activity, private val passStore: Pass
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val REQ_CODE_OFFSET = 5555
|
private const val REQ_CODE_OFFSET = 5555
|
||||||
val REQ_CODE_PICK_LOGO = 1 + REQ_CODE_OFFSET
|
const val REQ_CODE_PICK_LOGO = 1 + REQ_CODE_OFFSET
|
||||||
val REQ_CODE_PICK_ICON = 2 + REQ_CODE_OFFSET
|
const val REQ_CODE_PICK_ICON = 2 + REQ_CODE_OFFSET
|
||||||
val REQ_CODE_PICK_STRIP = 3 + REQ_CODE_OFFSET
|
const val REQ_CODE_PICK_STRIP = 3 + REQ_CODE_OFFSET
|
||||||
val REQ_CODE_PICK_THUMBNAIL = 4 + REQ_CODE_OFFSET
|
const val REQ_CODE_PICK_THUMBNAIL = 4 + REQ_CODE_OFFSET
|
||||||
val REQ_CODE_PICK_FOOTER = 5 + REQ_CODE_OFFSET
|
const val REQ_CODE_PICK_FOOTER = 5 + REQ_CODE_OFFSET
|
||||||
|
|
||||||
@Pass.PassBitmap
|
@Pass.PassBitmap
|
||||||
fun getImageStringByRequestCode(requestCode: Int): String? = when (requestCode) {
|
fun getImageStringByRequestCode(requestCode: Int): String? = when (requestCode) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui.edit.dialogs
|
package org.ligi.passandroid.ui.edit.dialogs
|
||||||
|
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.ligi.kaxt.inflate
|
import org.ligi.kaxt.inflate
|
||||||
import org.ligi.passandroid.R
|
import org.ligi.passandroid.R
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui.edit.dialogs
|
package org.ligi.passandroid.ui.edit.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui.edit.dialogs
|
package org.ligi.passandroid.ui.edit.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import kotlinx.android.synthetic.main.edit_color.view.*
|
import kotlinx.android.synthetic.main.edit_color.view.*
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.ligi.passandroid.ui.pass_view_holder
|
package org.ligi.passandroid.ui.pass_view_holder
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.support.v7.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import kotlinx.android.synthetic.main.pass_list_item.view.*
|
import kotlinx.android.synthetic.main.pass_list_item.view.*
|
||||||
import kotlinx.android.synthetic.main.time_and_nav.view.*
|
import kotlinx.android.synthetic.main.time_and_nav.view.*
|
||||||
|
|
|
@ -3,8 +3,8 @@ package org.ligi.passandroid.ui.pass_view_holder
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.DatePickerDialog
|
import android.app.DatePickerDialog
|
||||||
import android.app.TimePickerDialog
|
import android.app.TimePickerDialog
|
||||||
import android.support.v7.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.support.v7.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import android.widget.DatePicker
|
import android.widget.DatePicker
|
||||||
import android.widget.TimePicker
|
import android.widget.TimePicker
|
||||||
|
@ -19,9 +19,9 @@ import org.threeten.bp.ZonedDateTime
|
||||||
|
|
||||||
class EditViewHolder(view: CardView) : VerbosePassViewHolder(view), TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
|
class EditViewHolder(view: CardView) : VerbosePassViewHolder(view), TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
|
||||||
|
|
||||||
lateinit private var time: ZonedDateTime
|
private lateinit var time: ZonedDateTime
|
||||||
lateinit private var pass: PassImpl
|
private lateinit var pass: PassImpl
|
||||||
lateinit private var passStore: PassStore
|
private lateinit var passStore: PassStore
|
||||||
|
|
||||||
override fun apply(pass: Pass, passStore: PassStore, activity: Activity) {
|
override fun apply(pass: Pass, passStore: PassStore, activity: Activity) {
|
||||||
super.apply(pass, passStore, activity)
|
super.apply(pass, passStore, activity)
|
||||||
|
@ -30,7 +30,7 @@ class EditViewHolder(view: CardView) : VerbosePassViewHolder(view), TimePickerDi
|
||||||
this.passStore = passStore
|
this.passStore = passStore
|
||||||
|
|
||||||
val calendarTimespan = pass.calendarTimespan
|
val calendarTimespan = pass.calendarTimespan
|
||||||
time = if (calendarTimespan != null && calendarTimespan.from != null) {
|
time = if (calendarTimespan?.from != null) {
|
||||||
calendarTimespan.from
|
calendarTimespan.from
|
||||||
} else {
|
} else {
|
||||||
ZonedDateTime.now()
|
ZonedDateTime.now()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package org.ligi.passandroid.ui.pass_view_holder
|
package org.ligi.passandroid.ui.pass_view_holder
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.support.v7.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import android.view.View.*
|
import android.view.View.*
|
||||||
import kotlinx.android.synthetic.main.pass_list_item.view.*
|
import kotlinx.android.synthetic.main.pass_list_item.view.*
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue