Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c07ed1c
[wip] persistent project and initialization
ajungg Feb 3, 2022
c758eba
Rename .java to .kt
ajungg Feb 7, 2022
cad8177
convert Snabble to kotlin
ajungg Feb 7, 2022
8826770
make every fragment depend on BaseFragment
ajungg Feb 7, 2022
cca817d
persist config and project
ajungg Feb 8, 2022
faa9b1f
fix crash
ajungg Feb 8, 2022
f0bfc67
wait for initialization state in CheckoutActivity
ajungg Feb 10, 2022
6a0794d
remove config persistence
ajungg Feb 10, 2022
2ed52a9
Rename .java to .kt
ajungg Feb 10, 2022
ae8393b
persist shop, bugfixes and cleanup of initialization
ajungg Feb 10, 2022
7c03646
cleanup and bugfixes
ajungg Feb 11, 2022
8ae1182
only log keyguard error when it actually removed keys
ajungg Feb 11, 2022
9e5c8cc
fix self scanning view
ajungg Feb 11, 2022
de7efa6
Merge branch 'master' into persistance_and_initialization
ajungg Feb 11, 2022
d1d4136
use object for Snabble and fix tests
ajungg Feb 14, 2022
be1c4b1
more refactoring and cleanup
ajungg Feb 14, 2022
c78b1b0
do not inherit from Sample HomeFragment from BaseFragment, syntax imp…
ajungg Feb 15, 2022
ce75cfb
expand cases
ajungg Feb 15, 2022
1105e30
allow direct layout inflation of BaseFragment and add if project is r…
ajungg Feb 15, 2022
fc960b8
prevent overriding of baseclass methods
ajungg Feb 15, 2022
4c50c19
cleanup
ajungg Feb 15, 2022
86d952e
small fixes and clean up
ajungg Feb 15, 2022
18aec78
fix lint
ajungg Feb 15, 2022
4eb386c
compatibility fixes
ajungg Feb 15, 2022
fb69fde
fix repeated setup calls cleaning up properly
ajungg Feb 16, 2022
214e398
improve null safety
ajungg Feb 16, 2022
4fd2564
Fix imports and rarely formatting
rekire Feb 17, 2022
257ccea
Eliminate usage of Snabble.getInstance() in Kotlin code
rekire Feb 17, 2022
d99d0e1
Optimize imports and small formatting issues
rekire Feb 17, 2022
e1e52c1
Fix lint warnings
rekire Feb 18, 2022
85d112d
Ignore generated documentation
rekire Feb 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-base:$kotlin_version"
classpath 'com.android.tools.build:gradle:7.0.4'
classpath 'com.android.tools.build:gradle:7.1.1'
classpath 'gradle.plugin.com.github.jlouns:gradle-cross-platform-exec-plugin:0.5.0'
classpath 'gradle.plugin.gmazzo:sqlite-plugin:0.2'
}
Expand Down
12 changes: 5 additions & 7 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ android {
defaultConfig {
minSdkVersion project.minSdkVersion
targetSdkVersion project.targetSdkVersion
versionCode project.versionCode
versionName project.sdkVersion
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
consumerProguardFiles 'proguard-rules.pro'

Expand Down Expand Up @@ -59,17 +57,17 @@ dependencies {
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.iban4j:iban4j:3.2.1'
implementation 'com.caverock:androidsvg-aar:1.4'
implementation 'com.google.android.gms:play-services-wallet:18.1.3'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.biometric:biometric:1.2.0-alpha03'
implementation 'com.google.android.gms:play-services-wallet:19.1.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.biometric:biometric:1.2.0-alpha04'

api "com.squareup.okhttp3:okhttp:${project.okhttpVersion}"
implementation "com.squareup.okhttp3:logging-interceptor:${project.okhttpVersion}"

api 'com.google.code.gson:gson:2.8.8'
api 'com.google.code.gson:gson:2.8.9'

testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.6.1'
testImplementation 'org.robolectric:robolectric:4.7.3'
testImplementation "com.squareup.okhttp3:mockwebserver:${project.okhttpVersion}"

androidTestImplementation 'androidx.test:rules:1.4.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class AcceptedLanguageInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request: Request = chain.request()
val url = request.url.toString()
if (url.startsWith(Snabble.getInstance().endpointBaseUrl)) {
val baseUrl = Snabble.endpointBaseUrl
if (url.startsWith(baseUrl)) {
request = request.newBuilder()
.addHeader("Accept-Language", acceptedLanguagesHeader)
.build()
Expand Down
133 changes: 133 additions & 0 deletions core/src/main/java/io/snabble/sdk/Config.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package io.snabble.sdk

import android.content.Context
import io.snabble.sdk.utils.GsonHolder
import org.apache.commons.io.IOUtils
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

data class Config (
/**
* The endpoint url of the snabble backend. For example "https://api.snabble.io" for the Production environment.
*/
@JvmField
var endpointBaseUrl: String = Environment.PRODUCTION.baseUrl,

/**
* The project identifier, which is used in the communication with the backend.
*/
@JvmField
var appId: String? = null,

/**
* The secret needed for Totp token generation
*/
@JvmField
var secret: String? = null,

/**
* Relative path from the assets folder which points to a bundled file which contains the metadata
*
*
* This file gets initially used to initialize the sdk before network requests are made,
* or be able to use the sdk in the case of no network connection.
*
* Optional. If no file is specified every time the sdk is initialized we wait for a network response
* from the backend.
*
* It is HIGHLY recommended to provide bundled metadata to allow the sdk to function
* without having a network connection.
*/
@JvmField
var bundledMetadataAssetPath: String? = null,

/**
* Optional. Used to override the versionName appended to the metadata url.
*
* Defaults to the versionName in the app package.
*
* Must be in the format %d.%d
*/
@JvmField
var versionName: String? = null,

/**
* If set to true, creates an full text index to support searching in the product database
* using findByName or searchByName.
*
* Note that this increases setup time of the ProductDatabase, and it may not be
* immediately available offline.
*/
@JvmField
var generateSearchIndex: Boolean = false,

/**
* The time that the database is allowed to be out of date. After the specified time in
* milliseconds the database only uses online requests for asynchronous requests.
*
* Successfully calling [ProductDatabase.update] resets the timer.
*
* The time is specified in milliseconds.
*
* The default value is 1 hour.
*/
@JvmField
var maxProductDatabaseAge: Long = TimeUnit.HOURS.toMillis(1),

/**
* The time that the shopping cart is allowed to be alive after the last modification.
*
* The time is specified in milliseconds.
*
* The default value is 4 hours.
*/
@JvmField
var maxShoppingCartAge: Long = TimeUnit.HOURS.toMillis(4),

/** If set to true, disables certificate pinning */
@JvmField
var disableCertificatePinning: Boolean = false,

/** SQL queries that will get executed in order on the product database */
@JvmField
var initialSQL: List<String> = emptyList(),

/** Vibrate while adding a product to the cart, by default false */
@JvmField
var vibrateToConfirmCartFilled: Boolean = false,

/** Set to true, to load shops that are marked as pre launch
* and are not part of the original metadata in the backend
* (for example for testing shops in production before a go-live) */
@JvmField
var loadActiveShops: Boolean = false,

/**
* The radius in which the CheckInManager tries to check in a shop.
*
* In meters.
*/
@JvmField
var checkInRadius: Float = 500.0f,

/**
* The radius in which the CheckInManager tries to stay in a shop, if already in it.
* If outside of this radius and the lastSeenThreshold, you will be checked out.
*/
@JvmField
var checkOutRadius: Float = 1000.0f,

/**
* The time in milliseconds which we keep you checked in at a shop.
*
* The timer will be refreshed while you are still inside the shop
* and only begins to run if you are not inside the checkOutRadius anymore.
*/
@JvmField
var lastSeenThreshold: Long = TimeUnit.MINUTES.toMillis(15),
)
2 changes: 1 addition & 1 deletion core/src/main/java/io/snabble/sdk/Coupons.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class Coupons (
}
}
project.urls["coupons"]?.let { path ->
val couponsUrl = Snabble.getInstance().absoluteUrl(path) ?: return
val couponsUrl = Snabble.absoluteUrl(path)
isLoading.setAsap(true)

val request = Request.Builder()
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/java/io/snabble/sdk/InitializationState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.snabble.sdk

enum class InitializationState {
INITIALIZING,
INITIALIZED,
ERROR,
}
8 changes: 2 additions & 6 deletions core/src/main/java/io/snabble/sdk/OkHttpClientFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static OkHttpClient createOkHttpClient(Application application) {
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
builder.addInterceptor(logging);

Snabble.Config config = Snabble.getInstance().getConfig();
Config config = Snabble.getInstance().getConfig();
builder.addInterceptor(new UserAgentInterceptor(application));

if (!Snabble.getInstance().getConfig().disableCertificatePinning) {
Expand All @@ -56,11 +56,7 @@ static OkHttpClient createOkHttpClient(Application application) {
builder.certificatePinner(certificatePinnerBuilder.build());
}

if (config.sslSocketFactory != null && config.x509TrustManager != null) {
builder.sslSocketFactory(config.sslSocketFactory, config.x509TrustManager);
} else {
LetsEncryptCertHelper.addLetsEncryptCertificatesForMarshmallowOrEarlier(builder);
}
LetsEncryptCertHelper.addLetsEncryptCertificatesForMarshmallowOrEarlier(builder);

return builder.build();
}
Expand Down
8 changes: 3 additions & 5 deletions core/src/main/java/io/snabble/sdk/ProductDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,9 @@ public class ProductDatabase {
this.productApi = new ProductApi(project);

if (open()) {
String[] initialSQL = Snabble.getInstance().getConfig().initialSQL;
if (initialSQL != null) {
for (String sql : initialSQL) {
exec(sql);
}
List<String> initialSQL = Snabble.getInstance().getConfig().initialSQL;
for (String sql : initialSQL) {
exec(sql);
}
} else {
Logger.i("Product database is missing. Offline products are not available.");
Expand Down
12 changes: 7 additions & 5 deletions core/src/main/java/io/snabble/sdk/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class Project {

private RoundingMode roundingMode;
private BarcodeFormat[] supportedBarcodeFormats;
@Nullable
private Shop checkedInShop;
private CustomerCardInfo[] acceptedCustomerCardInfos;
private CustomerCardInfo requiredCustomerCardInfo;
Expand Down Expand Up @@ -95,13 +96,10 @@ public class Project {
.addInterceptor(new SnabbleAuthorizationInterceptor(this))
.addInterceptor(new AcceptedLanguageInterceptor())
.build();

parse(jsonObject);

internalStorageDirectory = new File(snabble.getInternalStorageDirectory(), id + "/");

boolean generateSearchIndex = snabble.getConfig().generateSearchIndex;

productDatabase = new ProductDatabase(this, id + ".sqlite3", generateSearchIndex);
shoppingCartStorage = new ShoppingCartStorage(this);
checkout = new Checkout(this);
Expand Down Expand Up @@ -320,7 +318,6 @@ void parse(JsonObject jsonObject) {
coupons.setInternalProjectCoupons(couponList);
}
coupons.update();

notifyUpdate();
}

Expand Down Expand Up @@ -490,12 +487,17 @@ public String getText(String key, String defaultValue) {
* Sets the shop used for receiving store specific prices and identification in the
* payment process.
*/
public void setCheckedInShop(Shop checkedInShop) {
public void setCheckedInShop(@Nullable Shop checkedInShop) {
String currentShopId = this.checkedInShop != null ? this.checkedInShop.getId() : "";
String newShopId = checkedInShop != null ? checkedInShop.getId() : "";

if (!currentShopId.equals(newShopId)) {
this.checkedInShop = checkedInShop;
if (newShopId.equals("")) {
snabble.getUserPreferences().setLastCheckedInShopId(null);
} else {
snabble.getUserPreferences().setLastCheckedInShopId(newShopId);
}
events.updateShop(checkedInShop);
getShoppingCart().updatePrices(false);
}
Expand Down
Loading