Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75c68bcc60 | ||
|
|
8375eebe71 |
@@ -20,7 +20,15 @@
|
||||
;; future, as we progressively fix shadowed
|
||||
;; vars, we should be able to delete this
|
||||
;; option and lint all vars.
|
||||
:exclude [type name]}
|
||||
:include [comparator
|
||||
count
|
||||
identity
|
||||
iter
|
||||
key
|
||||
str
|
||||
symbol
|
||||
time
|
||||
val]}
|
||||
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
|
||||
;; TODO remove number when this is fixed
|
||||
;; https://github.com/borkdude/clj-kondo/issues/867
|
||||
|
||||
@@ -224,7 +224,6 @@ release-android: keystore build-android ##@build Build signed Android APK
|
||||
@scripts/sign-android.sh result/app-release-unsigned.apk
|
||||
|
||||
release-ios: export TARGET := ios
|
||||
release-ios: export IOS_STATUS_GO_TARGETS := ios/arm64
|
||||
release-ios: export BUILD_ENV ?= prod
|
||||
release-ios: watchman-clean ios-clean jsbundle ##@build Build release for iOS release
|
||||
xcodebuild \
|
||||
@@ -273,14 +272,11 @@ run-re-frisk: ##@run Start re-frisk server
|
||||
|
||||
# TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix
|
||||
run-android: export TARGET := android
|
||||
# INFO: If it's empty (no devices attached, parsing issues, script error) - for Nix it's the same as not set.
|
||||
run-android: export ANDROID_ABI_INCLUDE ?= $(shell ./scripts/adb_devices_arch.sh)
|
||||
run-android: ##@run Build Android APK and start it on the device
|
||||
npx react-native run-android --appIdSuffix debug
|
||||
|
||||
SIMULATOR=iPhone 11 Pro
|
||||
run-ios: export TARGET := ios
|
||||
run-ios: export IOS_STATUS_GO_TARGETS := iossimulator/amd64
|
||||
run-ios: ##@run Build iOS app and start it in a simulator/device
|
||||
ifneq ("$(SIMULATOR)", "")
|
||||
npx react-native run-ios --simulator="$(SIMULATOR)"
|
||||
@@ -288,11 +284,11 @@ else
|
||||
npx react-native run-ios
|
||||
endif
|
||||
|
||||
show-ios-devices: export TARGET := ios
|
||||
show-ios-devices: ##@other shows connected ios device and its name
|
||||
xcrun xctrace list devices
|
||||
|
||||
run-ios-device: export TARGET := ios
|
||||
run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64
|
||||
run-ios-device: ##@run iOS app and start it on a connected device by its name
|
||||
ifndef DEVICE_NAME
|
||||
$(error Usage: make run-ios-device DEVICE_NAME=your-device-name)
|
||||
@@ -311,7 +307,7 @@ endef
|
||||
lint: export TARGET := clojure
|
||||
lint: ##@test Run code style checks
|
||||
@sh scripts/lint-re-frame-in-quo-components.sh && \
|
||||
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src && \
|
||||
clj-kondo --config .clj-kondo/config.edn --cache false --lint src && \
|
||||
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
|
||||
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
|
||||
sh scripts/lint-trailing-newline.sh && \
|
||||
@@ -351,11 +347,6 @@ test: ##@test Run tests once in NodeJS
|
||||
yarn shadow-cljs compile test && \
|
||||
node --require ./test-resources/override.js target/test/test.js
|
||||
|
||||
android-test: jsbundle
|
||||
android-test: export TARGET := android
|
||||
android-test:
|
||||
cd android && ./gradlew test
|
||||
|
||||
component-test-watch: export TARGET := clojure
|
||||
component-test-watch: export COMPONENT_TEST := true
|
||||
component-test-watch: export BABEL_ENV := test
|
||||
|
||||
@@ -4,6 +4,8 @@ apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.grad
|
||||
|
||||
import com.android.build.OutputFile
|
||||
import com.sun.org.apache.xalan.internal.xsltc.compiler.Copy
|
||||
import groovy.json.JsonBuilder
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
/**
|
||||
* The react.gradle file registers a task for each build variant:
|
||||
@@ -463,6 +465,32 @@ task hemroidBuild(type: Exec) {
|
||||
executable execPath
|
||||
}
|
||||
|
||||
// Add this task definition at the bottom of your build.gradle file
|
||||
task printAllDependencies {
|
||||
doLast {
|
||||
println "Listing all dependencies for project..."
|
||||
|
||||
// Iterate through all configurations
|
||||
configurations.all { config ->
|
||||
int dependencyCount = 0
|
||||
|
||||
// Count the dependencies for this configuration
|
||||
config.allDependencies.each { dependency ->
|
||||
dependencyCount++
|
||||
}
|
||||
|
||||
// Print the configuration name and dependency count
|
||||
println "Configuration: ${config.name} (Total Dependencies: ${dependencyCount})"
|
||||
|
||||
// Iterate through all dependencies in the current configuration
|
||||
config.allDependencies.each { dependency ->
|
||||
println " - ${dependency.group}:${dependency.name}:${dependency.version}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
preBuild.dependsOn hemroidBuild
|
||||
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: ['react-native-reanimated/plugin', '@babel/plugin-transform-named-capturing-groups-regex'],
|
||||
plugins: ['react-native-reanimated/plugin'],
|
||||
env: {
|
||||
test: {
|
||||
presets: [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@set_ios_status_go_targets'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
|
||||
@@ -83,7 +83,7 @@ pipeline {
|
||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 8 \
|
||||
--numprocesses 6 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-m testrail_id \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
|
||||
@@ -123,7 +123,7 @@ pipeline {
|
||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 8 \
|
||||
--numprocesses 6 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-k \"${params.KEYWORD_EXPRESSION}\" \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.12'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
2) Add some reviewers to the PR and wait for feedback
|
||||
3) Address feedback
|
||||
4) Make sure builds and tests are green (run `make test` locally, `make lint-fix` to fix any indentation issue and `make lint`)
|
||||
5) Once the PR has been reviewed by the dev team, run e2e tests on it by going to https://github.com/status-im/status-mobile/projects/7 and move the pr under the column E2E tests. This will trigger tests. **Running E2E tests is required for all PRs.**
|
||||
5) Once the PR has been reviewed by the dev team you can run e2e tests on it by going to https://github.com/status-im/status-mobile/projects/7 and move the pr under the column E2E tests. This will trigger tests.
|
||||
1) Read our [PR Review Policy](pr-review-policy.md) for more details on our approach to PR reviews.
|
||||
2) Learn more about our [Pipeline for QA](pipeline_process.md) process
|
||||
6) Once e2e tests have run, they will report the result on the PR, if it's less than 100%, ask QA to take a look to make sure everything is in order (some might fail for legitimate reasons)
|
||||
7) Ask QA for manual testing if the PR requires it (more details [here](pipeline_process.md))
|
||||
7) Ask QA for manual testing if the PR requires it
|
||||
8) Once it has been tested successfully, squash everything into one commit. rebase and merge. The commands we use:
|
||||
```
|
||||
git checkout develop
|
||||
|
||||
@@ -784,28 +784,6 @@ src
|
||||
└── view.cljs
|
||||
```
|
||||
|
||||
## Deprecation process
|
||||
|
||||
To deprecate a var, add the `:deprecated` metadata and, if necessary, suggest an
|
||||
alternative.
|
||||
|
||||
```clojure
|
||||
;; Good if there's no better alternative yet, but we want to deprecate it anyway.
|
||||
(defn ^:deprecated foo
|
||||
[]
|
||||
(bar))
|
||||
|
||||
;; Good
|
||||
(defn foo
|
||||
{:deprecated "Use some.namespace/var-name instead."}
|
||||
[]
|
||||
(bar))
|
||||
```
|
||||
|
||||
Please check the [Clojure Style](https://guide.clojure.style/#deprecated) documentation
|
||||
|
||||
To reduce visual clutter from deprecated methods in your text editor, consult this [example](https://rider-support.jetbrains.com/hc/en-us/community/posts/4419728641810-How-to-disable-the-the-strike-thru-for-deprecated-methods-in-Javascript-#:~:text=Try%20disabling%20%22Preferences%20%7C%20Editor%20%7C,It%20works%20for%20me). The approach can be adapted for settings in VSCode, Emacs, VIM, and others.
|
||||
|
||||
### Test structure
|
||||
|
||||
[Unit tests](#glossary) should be created alongside their respective source
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Pipeline process
|
||||
|
||||
[Pipeline for QA](https://github.com/status-im/status-mobile/projects/7) is a project board for developers and testers used to track the status of a pull request, get reviews and manual testing, and run autotests.
|
||||
[Pipeline for QA](https://github.com/status-im/status-mobile/projects/7) is a project board for developers and testers used to track the status of a pull request, get reviews and manual testing, _and run autotests_ (_temporary disabled_).
|
||||
|
||||
The generally accepted recommendations for its use are described below:
|
||||
|
||||
@@ -53,7 +53,7 @@ _**How do I know if a design review is needed?**_
|
||||
|
||||
There are three cases here depending on the changes in the PR:
|
||||
1. **Functional PRs with UI changes:** after the ```Tested - OK``` label is added, the QA moves the PR to the ```Design review``` column + mentions ```@Francesca-G``` in comments.
|
||||
2. **Component PRs:** once the PR has received a review from developers and e2e tests results, it can be moved directly to the ```Design review``` column by the developer (manual testing step can be skipped) + the developer mentions ```@Francesca-G``` in comments.
|
||||
2. **Component PRs:** can be moved directly to the ```Design review``` column by the developer when get a review from devs (manual testing step can be skipped) + the developer mentions ```@Francesca-G``` in comments.
|
||||
3. **Functional PRs changes in which are not related to UI (e.g. a crash fix):** skip the ```Design review``` step (the PR should only be manually tested by QA).
|
||||
|
||||
There are three possible scenarios when the design review is completed:
|
||||
@@ -75,11 +75,10 @@ In the second case - after fixing of all found issues, the developer should ping
|
||||
## Merging a PR
|
||||
**Merge conditions:**
|
||||
1. Required number of reviews received
|
||||
2. E2E results are received and reviewed
|
||||
3. All commits are squashed into one.
|
||||
4. No conflicting files in PR
|
||||
5. No issues from lint
|
||||
6. Pay attention to automation checks (some of them are not blockers, best to check before merge anyway)
|
||||
2. All commits are squashed into one.
|
||||
3. No conflicting files in PR
|
||||
4. No issues from lint
|
||||
5. Pay attention to automation checks (some of them are not blockers, best to check before merge anyway)
|
||||

|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,4 @@ dependencies {
|
||||
implementation 'com.github.status-im:function:0.0.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation(group: 'status-im', name: 'status-go', version: getStatusGoSHA1(), ext: 'aar')
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation "org.mockito:mockito-core:3.+"
|
||||
}
|
||||
|
||||
@@ -45,8 +45,7 @@ public class PushNotification extends ReactContextBaseJavaModule implements Acti
|
||||
reactContext.addActivityEventListener(this);
|
||||
Application applicationContext = (Application) reactContext.getApplicationContext();
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
pushNotificationHelper = new PushNotificationHelper(applicationContext, intentFilter);
|
||||
pushNotificationHelper = new PushNotificationHelper(applicationContext);
|
||||
|
||||
delivery = new PushNotificationJsDelivery(reactContext);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.app.NotificationManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -52,9 +51,7 @@ public class PushNotificationActions extends BroadcastReceiver {
|
||||
|
||||
// Notify the action.
|
||||
if(invokeApp) {
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
PushNotificationHelper helper = new PushNotificationHelper((Application) context.getApplicationContext(), intentFilter);
|
||||
PushNotificationHelper helper = new PushNotificationHelper((Application) context.getApplicationContext());
|
||||
|
||||
helper.invokeApp(bundle);
|
||||
} else {
|
||||
|
||||
@@ -76,11 +76,8 @@ public class PushNotificationHelper {
|
||||
private HashMap<String, Person> persons;
|
||||
private HashMap<String, StatusMessageGroup> messageGroups;
|
||||
|
||||
private IntentFilter intentFilter;
|
||||
|
||||
public PushNotificationHelper(Application context, IntentFilter intentFilter) {
|
||||
public PushNotificationHelper(Application context) {
|
||||
this.context = context;
|
||||
this.intentFilter = intentFilter;
|
||||
this.persons = new HashMap<String, Person>();
|
||||
this.messageGroups = new HashMap<String, StatusMessageGroup>();
|
||||
this.notificationManager = context.getSystemService(NotificationManager.class);
|
||||
@@ -136,10 +133,11 @@ public class PushNotificationHelper {
|
||||
}
|
||||
};
|
||||
|
||||
public void registerBroadcastReceiver() {
|
||||
this.intentFilter.addAction(ACTION_DELETE_NOTIFICATION);
|
||||
this.intentFilter.addAction(ACTION_TAP_STOP);
|
||||
context.registerReceiver(notificationActionReceiver, this.intentFilter);
|
||||
private void registerBroadcastReceiver() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_DELETE_NOTIFICATION);
|
||||
filter.addAction(ACTION_TAP_STOP);
|
||||
context.registerReceiver(notificationActionReceiver, filter);
|
||||
Log.e(LOG_TAG, "Broadcast Receiver registered");
|
||||
}
|
||||
|
||||
@@ -686,9 +684,13 @@ public class PushNotificationHelper {
|
||||
}
|
||||
|
||||
private Person getPerson(Bundle bundle) {
|
||||
String name = bundle.getString("name");
|
||||
String base64Image = bundle.getString("icon").split(",")[1];
|
||||
byte[] decodedString = Base64.decode(base64Image, Base64.DEFAULT);
|
||||
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
|
||||
|
||||
return new Person.Builder().setName(name).build();
|
||||
String name = bundle.getString("name");
|
||||
|
||||
return new Person.Builder().setIcon(IconCompat.createWithBitmap(getCircleBitmap(decodedByte))).setName(name).build();
|
||||
}
|
||||
|
||||
private StatusMessage createMessage(Bundle data) {
|
||||
@@ -737,10 +739,6 @@ public class PushNotificationHelper {
|
||||
this.showMessages(bundle);
|
||||
}
|
||||
|
||||
public StatusMessageGroup getMessageGroup(String conversationId) {
|
||||
return this.messageGroups.get(conversationId);
|
||||
}
|
||||
|
||||
public void addStatusMessage(Bundle bundle) {
|
||||
String conversationId = bundle.getString("conversationId");
|
||||
StatusMessageGroup group = this.messageGroups.get(conversationId);
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package android.util;
|
||||
|
||||
public class Log {
|
||||
public static int d(String tag, String msg) {
|
||||
System.out.println("DEBUG: " + tag + ": " + msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int i(String tag, String msg) {
|
||||
System.out.println("INFO: " + tag + ": " + msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int w(String tag, String msg) {
|
||||
System.out.println("WARN: " + tag + ": " + msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int e(String tag, String msg) {
|
||||
System.out.println("ERROR: " + tag + ": " + msg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package im.status.ethereum.pushnotifications;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import android.app.Application;
|
||||
import android.app.NotificationManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.IntentFilter;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.mockito.Spy;
|
||||
|
||||
public class PushNotificationHelperTest {
|
||||
|
||||
PushNotificationHelper helper;
|
||||
|
||||
|
||||
@Test
|
||||
public void testAddStatusMessage() {
|
||||
final Application context = mock(Application.class);
|
||||
final NotificationManager manager = mock(NotificationManager.class);
|
||||
final IntentFilter filter = mock(IntentFilter.class);
|
||||
|
||||
when(context.getSystemService(NotificationManager.class)).thenReturn(manager);
|
||||
|
||||
// Create a spy for PushNotificationHelper
|
||||
PushNotificationHelper realHelper = new PushNotificationHelper(context, filter);
|
||||
helper = spy(realHelper);
|
||||
|
||||
Bundle bundle = mock(Bundle.class);
|
||||
Bundle personBundle = mock(Bundle.class);
|
||||
|
||||
String conversationId = "conversation-id";
|
||||
String deepLink = "deep-link";
|
||||
|
||||
when(bundle.getString("conversationId")).thenReturn(conversationId);
|
||||
when(bundle.getString("id")).thenReturn("id");
|
||||
when(bundle.getString("message")).thenReturn("message");
|
||||
when(bundle.getDouble("timestamp")).thenReturn(100000.0);
|
||||
when(bundle.getString("deepLink")).thenReturn(deepLink);
|
||||
|
||||
when(personBundle.getString("name")).thenReturn("name");
|
||||
when(bundle.getBundle("notificationAuthor")).thenReturn(personBundle);
|
||||
|
||||
|
||||
doNothing().when(helper).showMessages(bundle);
|
||||
|
||||
helper.addStatusMessage(bundle);
|
||||
assertNotNull(helper.getMessageGroup(conversationId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,10 +631,7 @@ javax.inject:javax.inject:1
|
||||
javax.xml.bind:jaxb-api:2.2.12-b140109.1041
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
junit:junit:4.12
|
||||
junit:junit:4.13.2
|
||||
me.zhanghai.android.materialprogressbar:library:1.4.2
|
||||
net.bytebuddy:byte-buddy-agent:1.11.13
|
||||
net.bytebuddy:byte-buddy:1.11.13
|
||||
net.java.dev.jna:jna-platform:5.6.0
|
||||
net.java.dev.jna:jna:5.6.0
|
||||
net.sf.jopt-simple:jopt-simple:4.9
|
||||
@@ -791,8 +788,6 @@ org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.7.7
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.jvnet.staxex:stax-ex:1.8.1
|
||||
org.mockito:mockito-core:3.12.4
|
||||
org.objenesis:objenesis:3.2
|
||||
org.ow2.asm:asm-analysis:5.0.3
|
||||
org.ow2.asm:asm-analysis:5.1
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
|
||||
@@ -634,10 +634,10 @@ https://repo.maven.apache.org/maven2/com/google/auto/auto-parent/6/auto-parent-6
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/auto-parent/7/auto-parent-7.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.6.2/auto-value-annotations-1.6.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.6.3/auto-value-annotations-1.6.3.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.10.3/auto-value-annotations-1.10.3.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.10.2/auto-value-annotations-1.10.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.6.2/auto-value-parent-1.6.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.6.3/auto-value-parent-1.6.3.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.10.3/auto-value-parent-1.10.3.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.10.2/auto-value-parent-1.10.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value/1.5.2/auto-value-1.5.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.pom
|
||||
@@ -665,7 +665,7 @@ https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotatio
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.4.0/error_prone_annotations-2.4.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.7.1/error_prone_annotations-2.7.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.21.1/error_prone_annotations-2.21.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.20.0/error_prone_annotations-2.20.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.0.18/error_prone_parent-2.0.18.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.2.0/error_prone_parent-2.2.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.3.1/error_prone_parent-2.3.1.pom
|
||||
@@ -673,7 +673,7 @@ https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.3.4/error_prone_parent-2.3.4.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.4.0/error_prone_parent-2.4.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.7.1/error_prone_parent-2.7.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.21.1/error_prone_parent-2.21.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.20.0/error_prone_parent-2.20.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/flatbuffers/flatbuffers-java/1.12.0/flatbuffers-java-1.12.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/google/1/google-1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.pom
|
||||
@@ -688,8 +688,8 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/29.0-jre/guav
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/30.1-android/guava-parent-30.1-android.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/30.1-jre/guava-parent-30.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/31.0.1-jre/guava-parent-31.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/32.1.2-jre/guava-parent-32.1.2-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/32.1.2-jre/guava-testlib-32.1.2-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/32.1.1-jre/guava-parent-32.1.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/32.1.1-jre/guava-testlib-32.1.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/17.0/guava-17.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/22.0/guava-22.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/23.0/guava-23.0.pom
|
||||
@@ -701,7 +701,7 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1-android/guava-30.1-android.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1-jre/guava-30.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/32.1.1-jre/guava-32.1.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/1.0/listenablefuture-1.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.pom
|
||||
@@ -750,12 +750,12 @@ https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/3.12.1/okhttp-3
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/4.9.2/okhttp-4.9.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.9.1/parent-3.9.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.12.1/parent-3.12.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.5.0/okio-jvm-3.5.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.4.0/okio-jvm-3.4.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.17.4/okio-parent-1.17.4.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.17.4/okio-1.17.4.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.8.0/okio-2.8.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.9.0/okio-2.9.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.5.0/okio-3.5.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.4.0/okio-3.4.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.0/all-1.2.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.1/all-1.2.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.2/all-1.2.2.pom
|
||||
@@ -871,12 +871,9 @@ https://repo.maven.apache.org/maven2/javax/xml/stream/stax-api/1.0-2/stax-api-1.
|
||||
https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.pom
|
||||
https://repo.maven.apache.org/maven2/junit/junit/4.13.2/junit-4.13.2.pom
|
||||
https://repo.maven.apache.org/maven2/me/zhanghai/android/materialprogressbar/library/1.4.2/library-1.4.2.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.11.13/byte-buddy-agent-1.11.13.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.14.6/byte-buddy-agent-1.14.6.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.11.13/byte-buddy-parent-1.11.13.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.14.6/byte-buddy-parent-1.14.6.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.11.13/byte-buddy-1.11.13.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.14.6/byte-buddy-1.14.6.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.14.5/byte-buddy-agent-1.14.5.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.14.5/byte-buddy-parent-1.14.5.pom
|
||||
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.14.5/byte-buddy-1.14.5.pom
|
||||
https://repo.maven.apache.org/maven2/net/java/dev/jna/jna-platform/5.6.0/jna-platform-5.6.0.pom
|
||||
https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom
|
||||
https://repo.maven.apache.org/maven2/net/java/jvnet-parent/1/jvnet-parent-1.pom
|
||||
@@ -903,8 +900,8 @@ https://repo.maven.apache.org/maven2/org/abego/treelayout/org.abego.treelayout.c
|
||||
https://repo.maven.apache.org/maven2/org/antlr/ST4/4.0.8/ST4-4.0.8.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/ST4/4.3.4/ST4-4.3.4.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.5.3/antlr4-master-4.5.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.13.1/antlr4-master-4.13.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-runtime/4.13.1/antlr4-runtime-4.13.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.13.0/antlr4-master-4.13.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-runtime/4.13.0/antlr4-runtime-4.13.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4/4.5.3/antlr4-4.5.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr-master/3.3/antlr-master-3.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr-master/3.5.2/antlr-master-3.5.2.pom
|
||||
@@ -991,7 +988,7 @@ https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.8.1/che
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.5.0/checker-qual-3.5.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.38.0/checker-qual-3.38.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.36.0/checker-qual-3.36.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/codehaus-parent/4/codehaus-parent-4.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy-xml/3.0.10/groovy-xml-3.0.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy/3.0.9/groovy-3.0.9.pom
|
||||
@@ -1014,8 +1011,8 @@ https://repo.maven.apache.org/maven2/org/codehaus/woodstox/stax2-api/4.2.1/stax2
|
||||
https://repo.maven.apache.org/maven2/org/conscrypt/conscrypt-android/2.0.0/conscrypt-android-2.0.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/easymock/easymockclassextension/3.2/easymockclassextension-3.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/easymock/easymock-parent/3.2/easymock-parent-3.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/easymock/easymock-parent/5.2.0/easymock-parent-5.2.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/easymock/easymock/5.2.0/easymock-5.2.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/easymock/easymock-parent/5.1.0/easymock-parent-5.1.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/easymock/easymock/5.1.0/easymock-5.1.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/angus/angus-activation-project/2.0.1/angus-activation-project-2.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/angus/angus-activation/2.0.1/angus-activation-2.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/ee4j/project/1.0.2/project-1.0.2.pom
|
||||
@@ -1106,7 +1103,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.4.32/
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.5.31/kotlin-reflect-1.5.31.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.20/kotlin-reflect-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.10/kotlin-reflect-1.9.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.0/kotlin-reflect-1.9.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.10/kotlin-scripting-common-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.20/kotlin-scripting-common-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.10/kotlin-scripting-compiler-embeddable-1.6.10.pom
|
||||
@@ -1135,8 +1132,8 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.10/kotlin-stdlib-common-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.20/kotlin-stdlib-common-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.21/kotlin-stdlib-common-1.6.21.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.0/kotlin-stdlib-common-1.8.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.0/kotlin-stdlib-common-1.9.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.10/kotlin-stdlib-common-1.9.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.2.71/kotlin-stdlib-jdk7-1.2.71.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.20/kotlin-stdlib-jdk7-1.3.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.50/kotlin-stdlib-jdk7-1.3.50.pom
|
||||
@@ -1148,7 +1145,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.5
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.5.31/kotlin-stdlib-jdk7-1.5.31.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.20/kotlin-stdlib-jdk7-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.0/kotlin-stdlib-jdk7-1.9.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.0/kotlin-stdlib-jdk7-1.8.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.2.71/kotlin-stdlib-jdk8-1.2.71.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.20/kotlin-stdlib-jdk8-1.3.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.50/kotlin-stdlib-jdk8-1.3.50.pom
|
||||
@@ -1160,7 +1157,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.5
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.5.31/kotlin-stdlib-jdk8-1.5.31.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.20/kotlin-stdlib-jdk8-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.0/kotlin-stdlib-jdk8-1.9.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.0/kotlin-stdlib-jdk8-1.8.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.1.3-2/kotlin-stdlib-1.1.3-2.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.0/kotlin-stdlib-1.2.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.20/kotlin-stdlib-1.2.20.pom
|
||||
@@ -1182,8 +1179,8 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.5.31/k
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.10/kotlin-stdlib-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.20/kotlin-stdlib-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.21/kotlin-stdlib-1.6.21.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.8.0/kotlin-stdlib-1.8.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.0/kotlin-stdlib-1.9.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.10/kotlin-stdlib-1.9.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.10/kotlin-tooling-metadata-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.20/kotlin-tooling-metadata-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.6.10/kotlin-util-io-1.6.10.pom
|
||||
@@ -1202,11 +1199,8 @@ https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.7.7/stax-ex-1.7.
|
||||
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8.1/stax-ex-1.8.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8/stax-ex-1.8.pom
|
||||
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/2.1.0/stax-ex-2.1.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/3.12.4/mockito-core-3.12.4.pom
|
||||
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/5.5.0/mockito-core-5.5.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.2/objenesis-parent-3.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/5.4.0/mockito-core-5.4.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.3/objenesis-parent-3.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/objenesis/objenesis/3.2/objenesis-3.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/objenesis/objenesis/3.3/objenesis-3.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/5.1/asm-analysis-5.1.pom
|
||||
@@ -1252,11 +1246,10 @@ https://repo.maven.apache.org/maven2/org/ow2/ow2/1.5.1/ow2-1.5.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/ow2/ow2/1.5/ow2-1.5.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-bom/2.0.9/slf4j-bom-2.0.9.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/2.0.7/slf4j-api-2.0.7.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-parent/1.7.21/slf4j-parent-1.7.21.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-parent/1.7.30/slf4j-parent-1.7.30.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-parent/2.0.9/slf4j-parent-2.0.9.pom
|
||||
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-parent/2.0.7/slf4j-parent-2.0.7.pom
|
||||
https://repo.maven.apache.org/maven2/org/sonatype/oss/oss-parent/5/oss-parent-5.pom
|
||||
https://repo.maven.apache.org/maven2/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
|
||||
https://repo.maven.apache.org/maven2/org/sonatype/oss/oss-parent/9/oss-parent-9.pom
|
||||
|
||||
@@ -14,11 +14,6 @@ declare -a REPOS=(
|
||||
"https://jitpack.io"
|
||||
)
|
||||
|
||||
# These files are not necessary for the build process.
|
||||
FILENAMES_BLACKLIST='-(javadoc|runtime|gwt|headers|sources|src|tests|adapters|modular|site|bin)\.'
|
||||
FILETYPES_BLACKLIST='(pom|json|zip|module|xml|md5|sha1|sha256|sha512)$'
|
||||
SIGNATURE_BLACKLIST='(pom|jar|json|zip|module|xml|md5|asc).asc$'
|
||||
|
||||
function nix_prefetch() {
|
||||
nix store prefetch-file --json "${1}" 2>/dev/null
|
||||
}
|
||||
@@ -41,49 +36,7 @@ function match_repo_url() {
|
||||
|
||||
function pom_has_nodeps_jar() {
|
||||
grep '<shadedClassifierName>nodeps</shadedClassifierName>' "${1}" \
|
||||
>/dev/null 2>&1
|
||||
}
|
||||
|
||||
function guess_pkg_files() {
|
||||
# Some deps are just POMs, in which case there is no JAR to fetch.
|
||||
[[ "${OBJ_TYPE}" == "" ]] && echo "${PKG_NAME}.jar"
|
||||
[[ "${OBJ_TYPE}" == "jar" ]] && echo "${PKG_NAME}.jar"
|
||||
[[ "${OBJ_TYPE}" == "bundle" ]] && echo "${PKG_NAME}.jar"
|
||||
[[ "${OBJ_TYPE}" =~ aar* ]] && echo "${PKG_NAME}.aar"
|
||||
[[ "${OBJ_TYPE}" == "aar.asc" ]] && echo "${PKG_NAME}.${OBJ_TYPE}"
|
||||
pom_has_nodeps_jar "${POM_PATH}" && echo "${PKG_NAME}-nodeps.jar"
|
||||
}
|
||||
|
||||
function get_pkg_files() {
|
||||
REPO_URL="${1}"
|
||||
PKG_PATH="${2}"
|
||||
PKG_NAME="${3}"
|
||||
# Google Maven repo doesn't have normal HTML directory listing.
|
||||
if [[ "${REPO_URL}" == "https://dl.google.com/dl/android/maven2" ]]; then
|
||||
FOUND=$(curl --fail -s "${REPO_URL}/${PKG_PATH}/artifact-metadata.json")
|
||||
# Some older packages do not have artifacts-metadata.json.
|
||||
if [[ "$?" -eq 0 ]]; then
|
||||
FOUND=$(echo "${FOUND}" | jq -r '.artifacts[].name')
|
||||
else
|
||||
FOUND=''
|
||||
fi
|
||||
else
|
||||
FOUND=$(
|
||||
curl -s "${REPO_URL}/${PKG_PATH}/" \
|
||||
| htmlq a -a href \
|
||||
| grep -e "^${PKG_NAME}"
|
||||
)
|
||||
fi
|
||||
if [[ "${FOUND}" == '' ]]; then
|
||||
guess_pkg_files
|
||||
else
|
||||
# Filter out files we don't actually need for builds.
|
||||
echo "${FOUND}" \
|
||||
| grep -v -E \
|
||||
-e "${FILENAMES_BLACKLIST}" \
|
||||
-e "${FILETYPES_BLACKLIST}" \
|
||||
-e "${SIGNATURE_BLACKLIST}"
|
||||
fi
|
||||
>/dev/null 2>&1
|
||||
}
|
||||
|
||||
function fetch_and_template_file() {
|
||||
@@ -105,6 +58,10 @@ function fetch_and_template_file() {
|
||||
}"
|
||||
}
|
||||
|
||||
function fetch_and_template_file_no_fail() {
|
||||
fetch_and_template_file "${1}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
if [[ -z "${1}" ]]; then
|
||||
echo "Required POM URL argument not given!" >&2
|
||||
exit 1
|
||||
@@ -120,7 +77,7 @@ echo -en "${CLR} - Nix entry for: ${1##*/}\r" >&2
|
||||
REPO_URL=$(match_repo_url "${PKG_URL_NO_EXT}")
|
||||
|
||||
if [[ -z "${REPO_URL}" ]]; then
|
||||
echo " ! Repo URL not found for: ${POM_URL}" >&2
|
||||
echo " ! Repo URL not found: %s" "${REPO_URL}" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Get the relative path without full URL
|
||||
@@ -157,8 +114,12 @@ echo -ne "
|
||||
\"sha256\": \"${POM_SHA256}\"
|
||||
}"
|
||||
|
||||
for FILE in $(get_pkg_files "${REPO_URL}" "${PKG_PATH}" "${PKG_NAME}"); do
|
||||
fetch_and_template_file "${FILE}"
|
||||
done
|
||||
# Some deps are just POMs, in which case there is no JAR to fetch.
|
||||
[[ "${OBJ_TYPE}" == "" ]] && fetch_and_template_file_no_fail "${PKG_NAME}.jar"
|
||||
[[ "${OBJ_TYPE}" == "jar" ]] && fetch_and_template_file "${PKG_NAME}.jar"
|
||||
[[ "${OBJ_TYPE}" == "bundle" ]] && fetch_and_template_file "${PKG_NAME}.jar"
|
||||
[[ "${OBJ_TYPE}" =~ aar* ]] && fetch_and_template_file "${PKG_NAME}.aar"
|
||||
[[ "${OBJ_TYPE}" == "aar.asc" ]] && fetch_and_template_file "${PKG_NAME}.${OBJ_TYPE}"
|
||||
pom_has_nodeps_jar "${POM_PATH}" && fetch_and_template_file "${PKG_NAME}-nodeps.jar"
|
||||
|
||||
echo -e '\n }\n },'
|
||||
|
||||
@@ -3,33 +3,28 @@
|
||||
# It copies the status-go build result to 'modules/react-native-status/ios/RCTStatus'.
|
||||
#
|
||||
|
||||
{ lib, mkShell, status-go }:
|
||||
{ mkShell, status-go }:
|
||||
|
||||
let
|
||||
targets = let
|
||||
targetsString = lib.getEnvWithDefault "IOS_STATUS_GO_TARGETS" "ios/arm64;iossimulator/amd64";
|
||||
in lib.splitString ";" targetsString;
|
||||
in
|
||||
mkShell {
|
||||
shellHook = ''
|
||||
export STATUS_GO_IOS_LIBDIR=${status-go { inherit targets; } }/Statusgo.xcframework
|
||||
|
||||
RCTSTATUS_DIR="$STATUS_MOBILE_HOME/modules/react-native-status/ios/RCTStatus"
|
||||
targetBasename='Statusgo.xcframework'
|
||||
|
||||
# Compare target folder with source to see if copying is required
|
||||
if [ -d "$RCTSTATUS_DIR/$targetBasename" ] && [ -d $STATUS_MOBILE_HOME/ios/Pods/ ] && \
|
||||
diff -qr --no-dereference $RCTSTATUS_DIR/$targetBasename/ $STATUS_GO_IOS_LIBDIR/ > /dev/null; then
|
||||
echo "$RCTSTATUS_DIR/$targetBasename already in place"
|
||||
else
|
||||
sourceBasename="$(basename $STATUS_GO_IOS_LIBDIR)"
|
||||
echo "Copying $sourceBasename from Nix store to $RCTSTATUS_DIR"
|
||||
rm -rf "$RCTSTATUS_DIR/$targetBasename/"
|
||||
cp -a $STATUS_GO_IOS_LIBDIR $RCTSTATUS_DIR
|
||||
chmod -R 755 "$RCTSTATUS_DIR/$targetBasename"
|
||||
if [ "$sourceBasename" != "$targetBasename" ]; then
|
||||
mv "$RCTSTATUS_DIR/$sourceBasename" "$RCTSTATUS_DIR/$targetBasename"
|
||||
fi
|
||||
mkShell {
|
||||
shellHook = ''
|
||||
export STATUS_GO_IOS_LIBDIR=${status-go}/Statusgo.xcframework
|
||||
|
||||
RCTSTATUS_DIR="$STATUS_MOBILE_HOME/modules/react-native-status/ios/RCTStatus"
|
||||
targetBasename='Statusgo.xcframework'
|
||||
|
||||
# Compare target folder with source to see if copying is required
|
||||
if [ -d "$RCTSTATUS_DIR/$targetBasename" ] && [ -d $STATUS_MOBILE_HOME/ios/Pods/ ] && \
|
||||
diff -qr --no-dereference $RCTSTATUS_DIR/$targetBasename/ $STATUS_GO_IOS_LIBDIR/ > /dev/null; then
|
||||
echo "$RCTSTATUS_DIR/$targetBasename already in place"
|
||||
else
|
||||
sourceBasename="$(basename $STATUS_GO_IOS_LIBDIR)"
|
||||
echo "Copying $sourceBasename from Nix store to $RCTSTATUS_DIR"
|
||||
rm -rf "$RCTSTATUS_DIR/$targetBasename/"
|
||||
cp -a $STATUS_GO_IOS_LIBDIR $RCTSTATUS_DIR
|
||||
chmod -R 755 "$RCTSTATUS_DIR/$targetBasename"
|
||||
if [ "$sourceBasename" != "$targetBasename" ]; then
|
||||
mv "$RCTSTATUS_DIR/$sourceBasename" "$RCTSTATUS_DIR/$targetBasename"
|
||||
fi
|
||||
'';
|
||||
fi
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ let
|
||||
|
||||
# for running gradle by hand
|
||||
gradle = mkShell {
|
||||
buildInputs = with pkgs; [ gradle maven goMavenResolver htmlq ];
|
||||
buildInputs = with pkgs; [ gradle maven goMavenResolver ];
|
||||
shellHook = ''
|
||||
export STATUS_GO_ANDROID_LIBDIR="DUMMY"
|
||||
export STATUS_NIX_MAVEN_REPO="${pkgs.deps.gradle}"
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
inherit meta source goBuildLdFlags;
|
||||
};
|
||||
|
||||
ios = {targets ? [ "ios/arm64" "iossimulator/amd64"]}: callPackage ./build.nix {
|
||||
ios = callPackage ./build.nix {
|
||||
platform = "ios";
|
||||
platformVersion = "8.0";
|
||||
targets = [ "ios" "iossimulator" ];
|
||||
outputFileName = "Statusgo.xcframework";
|
||||
inherit meta source goBuildLdFlags targets;
|
||||
inherit meta source goBuildLdFlags;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"react-native-fetch-polyfill": "^1.1.2",
|
||||
"react-native-fs": "^2.14.1",
|
||||
"react-native-gesture-handler": "2.6.1",
|
||||
"react-native-gifted-charts": "git+https://github.com/status-im/react-native-gifted-charts.git#refs/tags/1.3.2-status.1",
|
||||
"react-native-gifted-charts": "^1.3.2",
|
||||
"react-native-haptic-feedback": "^1.9.0",
|
||||
"react-native-hole-view": "git+https://github.com/status-im/react-native-hole-view.git#refs/tags/v2.1.3-status",
|
||||
"react-native-image-crop-picker": "git+https://github.com/status-im/react-native-image-crop-picker.git#refs/tags/v0.36.2-status.0",
|
||||
@@ -82,7 +82,6 @@
|
||||
"@babel/generator": "7.0.0",
|
||||
"@babel/helper-builder-react-jsx": "7.0.0",
|
||||
"@babel/plugin-transform-block-scoping": "7.0.0",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
|
||||
"@babel/preset-env": "7.1.0",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/register": "7.0.0",
|
||||
|
||||
|
Before Width: | Height: | Size: 731 B After Width: | Height: | Size: 676 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 964 B |
|
Before Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 879 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 443 KiB |
|
Before Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 317 KiB |
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
typeset -a abis
|
||||
SCRIPT_NAME=$(basename $0)
|
||||
|
||||
function log() {
|
||||
echo "${SCRIPT_NAME} ${1}: ${2}" >&2
|
||||
}
|
||||
|
||||
# make sure server is running, otherwise sdb will show devices offline
|
||||
adb start-server
|
||||
|
||||
while IFS= read line; do
|
||||
read -a arr <<< "${line}"
|
||||
|
||||
device_name="${arr[0]}"
|
||||
device_status=${arr[1]}
|
||||
|
||||
log "DEBUG" "device_name=${device_name}"
|
||||
log "DEBUG" "device_status=${device_status}"
|
||||
|
||||
if [[ "${device_status}" != "device" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
device_product_abi=$(adb -s ${device_name} shell -n getprop ro.product.cpu.abi)
|
||||
log "DEBUG" "device_product_abi=${device_product_abi}"
|
||||
|
||||
if [[ ! ${abis[*]} =~ ${device_product_abi} ]]; then
|
||||
abis+=("${device_product_abi}")
|
||||
fi
|
||||
done <<< "$(adb devices | tail -n+2)"
|
||||
|
||||
if [[ ! "${abis[*]}" ]]; then
|
||||
log "ERROR" "no devices found. Check 'adb devices -l' output and share with Infra team if needed."
|
||||
exit 3
|
||||
fi
|
||||
|
||||
log "DEBUG" "resulting abis:"
|
||||
IFS=\;; echo "${abis[*]}"
|
||||
@@ -66,14 +66,10 @@
|
||||
status-im2.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
:compiler-options {:output-feature-set :es5
|
||||
;; We disable `:fn-deprecated` warnings because we
|
||||
;; are managing deprecation via clj-kondo and we
|
||||
;; don't want the terminal output to be littered
|
||||
;; with warnings on every code reload.
|
||||
:warnings {:fn-deprecated false}
|
||||
:closure-defines {re-frame.trace/trace-enabled? true}
|
||||
:source-map false
|
||||
:infer-externs true}
|
||||
:closure-defines
|
||||
{re-frame.trace/trace-enabled? true}
|
||||
:source-map false
|
||||
:infer-externs true}
|
||||
;; if you want to use a real device, set your local ip
|
||||
;; in the SHADOW_HOST env variable to make sure that
|
||||
;; it will use the right interface
|
||||
|
||||
@@ -389,11 +389,11 @@
|
||||
[]
|
||||
(log/debug "[native-module] get-device-model-info")
|
||||
;;NOTE: we have to check for status module because of tests
|
||||
(when-let [^js status-module (status)]
|
||||
{:model (.-model status-module)
|
||||
:brand (.-brand status-module)
|
||||
:build-id (.-buildId status-module)
|
||||
:device-id (.-deviceId status-module)}))
|
||||
(when-let [^js status (status)]
|
||||
{:model (.-model status)
|
||||
:brand (.-brand status)
|
||||
:build-id (.-buildId status)
|
||||
:device-id (.-deviceId status)}))
|
||||
|
||||
(defn get-installation-name
|
||||
[]
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def left-style
|
||||
(def left
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
@@ -43,7 +43,7 @@
|
||||
:justify-content :center
|
||||
:align-items :flex-start})
|
||||
|
||||
(def right-style
|
||||
(def right
|
||||
{:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
@@ -179,7 +179,7 @@
|
||||
{:style content
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style left-style
|
||||
{:style left
|
||||
:on-layout (handle-layout :left get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
@@ -197,7 +197,7 @@
|
||||
:component title-component}]]
|
||||
|
||||
[rn/view
|
||||
{:style right-style
|
||||
{:style right
|
||||
:on-layout (handle-layout :right get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
(ns quo.previews.preview)
|
||||
|
||||
(defmacro list-comp
|
||||
[[the-binding seq-expr & bindings] body-expr]
|
||||
(cond (not the-binding)
|
||||
[[binding seq-expr & bindings] body-expr]
|
||||
(cond (not binding)
|
||||
`(list ~body-expr)
|
||||
|
||||
:else
|
||||
`(mapcat (fn [~the-binding] (list-comp ~bindings ~body-expr))
|
||||
`(mapcat (fn [~binding] (list-comp ~bindings ~body-expr))
|
||||
~seq-expr)))
|
||||
|
||||
@@ -4,23 +4,21 @@
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private sizes
|
||||
{:size/s-48 {:component 48
|
||||
:icon 20}
|
||||
:size/s-32 {:component 32
|
||||
:icon 20}
|
||||
:size/s-24 {:component 24
|
||||
:icon 16}
|
||||
:size/s-20 {:component 20
|
||||
:icon 12}})
|
||||
(def sizes
|
||||
{:big 48
|
||||
:medium 32
|
||||
:small 20})
|
||||
|
||||
(defn icon-avatar-internal
|
||||
[{:keys [size icon color opacity border? theme]
|
||||
:or {opacity 20
|
||||
size :size/s-32}}]
|
||||
(let [{component-size :component icon-size :icon} (get sizes size)
|
||||
circle-color (colors/custom-color color 50 opacity)
|
||||
icon-color (colors/custom-color-by-theme color 50 60)]
|
||||
:or {opacity 20}}]
|
||||
(let [component-size (size sizes)
|
||||
circle-color (colors/custom-color color 50 opacity)
|
||||
icon-color (colors/custom-color-by-theme color 50 60)
|
||||
icon-size (case size
|
||||
:big 20
|
||||
:medium 16
|
||||
:small 12)]
|
||||
[rn/view
|
||||
{:style {:width component-size
|
||||
:height component-size
|
||||
|
||||
@@ -2,48 +2,34 @@
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def sizes
|
||||
{:big {:dimensions 80
|
||||
:status-indicator 12
|
||||
:status-indicator-border 4
|
||||
:status-indicator-center-to-edge 12
|
||||
:font-size :heading-1
|
||||
:ring-width 4}
|
||||
:medium {:dimensions 48
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 6
|
||||
:font-size :heading-2
|
||||
:ring-width 2}
|
||||
:small {:dimensions 32
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 4
|
||||
:font-size :paragraph-2
|
||||
:ring-width 2}
|
||||
28 {:dimensions 28
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :paragraph-2
|
||||
:ring-width 0}
|
||||
:xs {:dimensions 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :paragraph-2
|
||||
:ring-width 2}
|
||||
:xxs {:dimensions 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :label
|
||||
:ring-width 2}
|
||||
:xxxs {:dimensions 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :label
|
||||
:ring-width 2}})
|
||||
{:big {:dimensions 80
|
||||
:status-indicator 20
|
||||
:status-indicator-border 4
|
||||
:font-size :heading-1}
|
||||
:medium {:dimensions 48
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :heading-2}
|
||||
:small {:dimensions 32
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-2}
|
||||
28 {:dimensions 28
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :paragraph-2}
|
||||
:xs {:dimensions 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :paragraph-2}
|
||||
:xxs {:dimensions 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}
|
||||
:xxxs {:dimensions 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}})
|
||||
|
||||
(defn initials-avatar
|
||||
[size customization-color theme]
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
:indicator-size status indicator outer radius, set to nil or 0 when no indicator
|
||||
:indicator-border `indicator-size`-`indicator-border` is the inner radius
|
||||
:indicator-color color for status indicator
|
||||
:theme :light or :dark
|
||||
:override-theme override theme for ring
|
||||
:background-color intials avatar background color
|
||||
:color intials avatar text color
|
||||
:size intials avatar radius
|
||||
@@ -55,7 +55,7 @@
|
||||
status-indicator? true
|
||||
online? true
|
||||
ring? true
|
||||
customization-color :blue}
|
||||
customization-color :turquoise}
|
||||
:as props}]
|
||||
(let [full-name (or full-name "Your Name")
|
||||
;; image generated with profile-picture-fn is round cropped
|
||||
@@ -83,23 +83,20 @@
|
||||
:source
|
||||
(cond profile-picture-fn
|
||||
{:uri (profile-picture-fn
|
||||
{:length amount-initials
|
||||
:full-name full-name
|
||||
:font-size (:font-size (text/text-style {:size
|
||||
font-size}))
|
||||
:indicator-size (when status-indicator?
|
||||
(:status-indicator sizes))
|
||||
:indicator-border (when status-indicator?
|
||||
(:status-indicator-border sizes))
|
||||
:indicator-center-to-edge (when status-indicator?
|
||||
(:status-indicator-center-to-edge sizes))
|
||||
:indicator-color indicator-color
|
||||
:override-theme theme
|
||||
:background-color (style/customization-color customization-color theme)
|
||||
:color (:color style/initials-avatar-text)
|
||||
:size (:width outer-styles)
|
||||
:ring? ring?
|
||||
:ring-width (:ring-width sizes)})}
|
||||
{:length amount-initials
|
||||
:full-name full-name
|
||||
:font-size (:font-size (text/text-style {:size
|
||||
font-size}))
|
||||
:indicator-size (when status-indicator?
|
||||
(:status-indicator sizes))
|
||||
:indicator-border (when status-indicator?
|
||||
(:status-indicator-border sizes))
|
||||
:indicator-color indicator-color
|
||||
:override-theme theme
|
||||
:background-color (style/customization-color customization-color theme)
|
||||
:color (:color style/initials-avatar-text)
|
||||
:size (:width outer-styles)
|
||||
:ring? ring?})}
|
||||
(:uri profile-picture)
|
||||
profile-picture
|
||||
|
||||
|
||||
@@ -85,14 +85,14 @@
|
||||
56 0
|
||||
40 (if border-color 8 9)
|
||||
32 (if border-color 4 5)
|
||||
24 0
|
||||
24 (if border-color 0 1)
|
||||
(if border-color 8 9)))
|
||||
:padding-bottom (when-not (or icon-only? icon-left icon-right)
|
||||
(case size
|
||||
56 0
|
||||
40 9
|
||||
32 5
|
||||
24 0
|
||||
24 4
|
||||
9))
|
||||
:overflow :hidden
|
||||
:background-color background-color
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
Reagent and React render."
|
||||
[f]
|
||||
(js/Promise.
|
||||
(fn [resolve-fn reject]
|
||||
(fn [resolve reject]
|
||||
(try
|
||||
(.then (rtl/act
|
||||
#(let [p (js/Promise. (fn [resolve-fn2 _reject]
|
||||
#(let [p (js/Promise. (fn [resolve _reject]
|
||||
(r/after-render (fn reagent-act-after-reagent-flush []
|
||||
(resolve-fn2)))))]
|
||||
(resolve)))))]
|
||||
(f)
|
||||
p))
|
||||
resolve-fn
|
||||
resolve
|
||||
reject)
|
||||
(catch :default e
|
||||
(reject e))))))
|
||||
@@ -117,3 +117,4 @@
|
||||
gesture-events)))]
|
||||
(h/advance-timers-by-time 250)
|
||||
(-> promise (.then #(h/was-not-called (:on-complete props))))))))
|
||||
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
(def ^:const size 8)
|
||||
|
||||
(defn dot-background-color
|
||||
[customization-color theme blur?]
|
||||
(cond
|
||||
customization-color (colors/theme-colors
|
||||
(colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme)
|
||||
blur? (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
|
||||
:else (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
|
||||
[customization-color theme]
|
||||
(if customization-color
|
||||
(colors/theme-colors
|
||||
(colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme)
|
||||
(colors/theme-colors colors/primary-50 colors/primary-60 theme)))
|
||||
|
||||
(defn notification-dot
|
||||
[customization-color theme blur?]
|
||||
{:background-color (dot-background-color customization-color theme blur?)
|
||||
[customization-color theme]
|
||||
{:background-color (dot-background-color customization-color theme)
|
||||
:width size
|
||||
:height size
|
||||
:border-radius (/ size 2)
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
[quo2.theme :as quo.theme]))
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [customization-color style theme blur?]}]
|
||||
[{:keys [customization-color style theme]}]
|
||||
[rn/view
|
||||
{:accessibility-label :notification-dot
|
||||
:style (merge
|
||||
(style/notification-dot customization-color theme blur?)
|
||||
(style/notification-dot customization-color theme)
|
||||
style)}])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns quo2.components.dividers.divider-line.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn divider-line
|
||||
[blur? theme]
|
||||
{:border-color (if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-90 theme))
|
||||
:padding-top 12
|
||||
:padding-bottom 8
|
||||
:border-bottom-width 1})
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns quo2.components.dividers.divider-line.view
|
||||
(:require
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.dividers.divider-line.style :as style]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [blur? theme]}]
|
||||
[rn/view {:style (style/divider-line blur? theme)}])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns quo2.components.graph.interactive-graph.component-spec
|
||||
(:require [test-helpers.component :as h]
|
||||
[quo2.components.graph.interactive-graph.view :as interactive-graph]))
|
||||
|
||||
(defn data
|
||||
[num-elements]
|
||||
(vec (take num-elements (repeat {:value 10}))))
|
||||
|
||||
(h/describe "interactive-graph"
|
||||
(h/test "render interactive graph"
|
||||
(h/render [interactive-graph/view
|
||||
{:data data}])
|
||||
(h/is-truthy (h/get-by-label-text :interactive-graph))))
|
||||
@@ -1,49 +0,0 @@
|
||||
(ns quo2.components.graph.interactive-graph.style
|
||||
(:require [quo2.foundations.typography :as typography]))
|
||||
|
||||
(defn x-axis-label-text
|
||||
[width y-axis-label-text-color]
|
||||
(merge
|
||||
typography/label
|
||||
{:color y-axis-label-text-color
|
||||
:height 16
|
||||
:text-align :center
|
||||
:width width}))
|
||||
|
||||
(defn y-axis-text
|
||||
[y-axis-label-text-color y-axis-label-background-color]
|
||||
(merge
|
||||
typography/label
|
||||
{:color y-axis-label-text-color
|
||||
:padding-horizontal 3
|
||||
:margin-left 23
|
||||
:height 16
|
||||
:border-radius 6
|
||||
:overflow :hidden
|
||||
:background-color y-axis-label-background-color}))
|
||||
|
||||
(defn pointer-component
|
||||
[customization-color]
|
||||
{:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:margin-left 1
|
||||
:background-color customization-color})
|
||||
|
||||
(defn reference-line-label
|
||||
[border-color background-color text-color]
|
||||
(merge
|
||||
typography/label
|
||||
{:align-self :flex-end
|
||||
:right 10
|
||||
:margin-top -9
|
||||
:padding-horizontal 5
|
||||
:padding-top -10
|
||||
:height 19
|
||||
:line-height 14.62
|
||||
:border-radius 6
|
||||
:overflow :hidden
|
||||
:border-color border-color
|
||||
:border-width 2
|
||||
:background-color background-color
|
||||
:color text-color}))
|
||||
@@ -1,141 +0,0 @@
|
||||
(ns quo2.components.graph.interactive-graph.view
|
||||
(:require [quo2.components.graph.utils :as utils]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.charts :as charts]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.graph.interactive-graph.style :as style]))
|
||||
|
||||
(def chart-height 375)
|
||||
(def max-data-points 500)
|
||||
(def no-of-sections 4)
|
||||
(def initial-spacing 56)
|
||||
(def end-spacing 22)
|
||||
(def y-axis-label-width -33)
|
||||
(def inspecting? (reagent/atom false))
|
||||
|
||||
(defn- pointer
|
||||
[customization-color]
|
||||
(reagent/as-element
|
||||
[rn/view
|
||||
{:style
|
||||
(style/pointer-component
|
||||
customization-color)}]))
|
||||
|
||||
(defn- pointer-config
|
||||
[customization-color]
|
||||
{:stroke-dash-array [2 2]
|
||||
:pointer-component #(pointer customization-color)
|
||||
:pointer-strip-color customization-color
|
||||
:pointer-color customization-color
|
||||
:pointer-strip-enable-gradient true})
|
||||
|
||||
(defn- get-pointer-props
|
||||
[pointer-props]
|
||||
(let [pointer-index (.-pointerIndex ^js pointer-props)]
|
||||
(reset! inspecting? (not= pointer-index -1))))
|
||||
|
||||
(defn- get-line-color
|
||||
[state theme]
|
||||
(if @inspecting?
|
||||
(colors/theme-colors colors/neutral-80-opa-40
|
||||
colors/white-opa-20
|
||||
theme)
|
||||
(if (= state :positive)
|
||||
(colors/theme-colors colors/success-50
|
||||
colors/success-60
|
||||
theme)
|
||||
(colors/theme-colors colors/danger-50
|
||||
colors/danger-60
|
||||
theme))))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [data state customization-color theme reference-value reference-prefix decimal-separator]
|
||||
:or {reference-prefix "$"
|
||||
decimal-separator :dot}}]
|
||||
(let [data (if (> (count data) max-data-points)
|
||||
(utils/downsample-data data max-data-points)
|
||||
data)
|
||||
highest-value (utils/find-highest-value data)
|
||||
lowest-value (utils/find-lowest-value data)
|
||||
min-value (utils/calculate-rounded-min lowest-value)
|
||||
max-value (- (utils/calculate-rounded-max highest-value) min-value)
|
||||
step-value (/ max-value 4)
|
||||
width (:width (rn/get-window))
|
||||
line-color (get-line-color state theme)
|
||||
rules-color (colors/theme-colors colors/neutral-80-opa-10
|
||||
colors/white-opa-5
|
||||
theme)
|
||||
y-axis-label-text-color (colors/theme-colors colors/neutral-80-opa-40
|
||||
colors/white-opa-40
|
||||
theme)
|
||||
price-reference-label-text-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
reference-label-border-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
y-axis-label-background-color (colors/theme-colors colors/white-70-blur-opaque
|
||||
colors/neutral-95
|
||||
theme)
|
||||
customization-color (colors/theme-colors
|
||||
(colors/custom-color customization-color 60)
|
||||
(colors/custom-color customization-color 50)
|
||||
theme)
|
||||
y-axis-label-texts (utils/calculate-y-axis-labels min-value step-value 4)
|
||||
x-axis-label-texts (utils/calculate-x-axis-labels data 5)
|
||||
reference-label-background-color (colors/theme-colors colors/neutral-80-opa-5-opaque
|
||||
colors/neutral-80
|
||||
theme)
|
||||
reference-value (or reference-value (/ (+ highest-value lowest-value) 2))
|
||||
formatted-reference-value (utils/format-currency-number reference-value decimal-separator)
|
||||
chart-width (+ width 13)]
|
||||
[rn/view {:accessibility-label :interactive-graph}
|
||||
[charts/line-chart
|
||||
{:height chart-height
|
||||
:width chart-width
|
||||
:max-value max-value
|
||||
:x-axis-length chart-width
|
||||
:y-axis-offset min-value
|
||||
:y-axis-label-texts y-axis-label-texts
|
||||
:y-axis-label-texts-ignore-offset true
|
||||
:adjust-to-width true
|
||||
:data data
|
||||
:hide-data-points true
|
||||
:no-of-sections no-of-sections
|
||||
:step-value step-value
|
||||
:rules-color rules-color
|
||||
:dash-width 2
|
||||
:dash-gap 2
|
||||
:hide-y-axis-text false
|
||||
:thickness 1
|
||||
:color line-color
|
||||
:y-axis-thickness 0
|
||||
:x-axis-thickness 0
|
||||
:initial-spacing initial-spacing
|
||||
:end-spacing end-spacing
|
||||
:disable-scroll true
|
||||
:hide-origin true
|
||||
:show-reference-line-1 true
|
||||
:get-pointer-props get-pointer-props
|
||||
:show-strip-on-focus true
|
||||
:reference-line-1-config {:color rules-color}
|
||||
:reference-line-1-position 0
|
||||
:show-reference-line-2 (and (not @inspecting?)
|
||||
(<= reference-value highest-value)
|
||||
(>= reference-value lowest-value))
|
||||
:reference-line-2-config {:color y-axis-label-text-color
|
||||
:label-text-style (style/reference-line-label
|
||||
reference-label-border-color
|
||||
reference-label-background-color
|
||||
price-reference-label-text-color)
|
||||
:label-text (str reference-prefix
|
||||
formatted-reference-value)
|
||||
:dash-width 2}
|
||||
:reference-line-2-position (- reference-value min-value)
|
||||
:y-axis-text-style (style/y-axis-text y-axis-label-text-color
|
||||
y-axis-label-background-color)
|
||||
:y-axis-label-width y-axis-label-width
|
||||
:pointer-config (pointer-config customization-color)
|
||||
:x-axis-label-text-style (style/x-axis-label-text (/ width (count x-axis-label-texts))
|
||||
y-axis-label-text-color)
|
||||
:x-axis-label-texts x-axis-label-texts}]]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -1,95 +0,0 @@
|
||||
(ns quo2.components.graph.utils
|
||||
(:require [clojure.string :as string]
|
||||
[goog.string :as gstring]))
|
||||
|
||||
(defn find-highest-value
|
||||
[coll]
|
||||
(apply max (map :value coll)))
|
||||
|
||||
(defn find-lowest-value
|
||||
[coll]
|
||||
(apply min (map :value coll)))
|
||||
|
||||
(defn downsample-data
|
||||
[data max-array-size]
|
||||
(let [data-size (count data)]
|
||||
(if (> data-size max-array-size)
|
||||
(let [step-size (max (/ data-size max-array-size) 1)]
|
||||
(vec (take-nth step-size data)))
|
||||
data)))
|
||||
|
||||
(defn format-compact-number
|
||||
[number]
|
||||
(let [abbreviations ["" "k" "M" "B" "T"]
|
||||
log-base-1000 (js/Math.log10 1000) ; Calculate the logarithm base 1000
|
||||
magnitude (int (/ (js/Math.log10 number) log-base-1000))
|
||||
suffix (nth abbreviations magnitude)
|
||||
scaled-number (/ number (js/Math.pow 1000.0 magnitude))
|
||||
formatted-scaled-number (if (zero? (rem scaled-number 1))
|
||||
(int scaled-number)
|
||||
(-> (gstring/format "%.2f" scaled-number)
|
||||
(string/replace #"\.?0+$" "")))]
|
||||
(if (zero? magnitude)
|
||||
(str number)
|
||||
(if (and (>= scaled-number 1) (< scaled-number 1000))
|
||||
(str formatted-scaled-number suffix)
|
||||
(str formatted-scaled-number "0" suffix)))))
|
||||
|
||||
(defn calculate-x-axis-labels
|
||||
[coll num-elements]
|
||||
(let [array-length (count coll)
|
||||
partitions (partition-all (js/Math.floor (/ array-length (min array-length num-elements)))
|
||||
coll)]
|
||||
(->> partitions
|
||||
(map first)
|
||||
(map :date))))
|
||||
|
||||
(defn calculate-y-axis-labels
|
||||
[min-value step-value no-of-steps]
|
||||
(let [labels-array (for [i (range (inc no-of-steps))]
|
||||
(let [value (+ min-value (* step-value i))
|
||||
compact-number (format-compact-number value)]
|
||||
compact-number))]
|
||||
(vec labels-array)))
|
||||
|
||||
(defn calculate-rounded-max
|
||||
[highest-value]
|
||||
(let [min-percentage-above 1.05 ; 5% above
|
||||
rounded-divisor 4 ; Divisor for even division by 4
|
||||
target-max (* min-percentage-above highest-value)
|
||||
rounded-up (js/Math.ceil target-max)
|
||||
remainder (mod rounded-up rounded-divisor)
|
||||
y-axis-max (if (zero? remainder)
|
||||
rounded-up
|
||||
(+ rounded-up (- rounded-divisor remainder)))]
|
||||
y-axis-max))
|
||||
|
||||
(defn calculate-rounded-min
|
||||
[lowest]
|
||||
(let [order-of-magnitude (js/Math.pow 10 (js/Math.floor (js/Math.log10 lowest)))
|
||||
rounded-min (cond
|
||||
(and (< lowest 1) (>= lowest 0)) 0
|
||||
(>= lowest 1)
|
||||
(* (js/Math.floor (/ lowest
|
||||
order-of-magnitude))
|
||||
order-of-magnitude)
|
||||
(< lowest 0)
|
||||
(* (calculate-rounded-max (* -1 lowest))
|
||||
-1))]
|
||||
rounded-min))
|
||||
|
||||
(defn format-currency-number
|
||||
[number decimal-separator]
|
||||
(let [formatted (-> (if (= decimal-separator :comma)
|
||||
(js/Intl.NumberFormat
|
||||
"de-DE"
|
||||
{:style "currency" :currency "EUR" :minimumFractionDigits 2})
|
||||
(js/Intl.NumberFormat
|
||||
"en-US"
|
||||
{:style "currency" :currency "USD" :minimumFractionDigits 2}))
|
||||
(.format number))
|
||||
separator-char (if (= decimal-separator :comma) "," ".")
|
||||
formatted-with-decimals (if (.includes formatted separator-char)
|
||||
formatted
|
||||
(str formatted separator-char "00"))]
|
||||
formatted-with-decimals))
|
||||
@@ -1,179 +0,0 @@
|
||||
(ns quo2.components.graph.utils-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[quo2.components.graph.utils :as utils]))
|
||||
|
||||
(deftest find-highest-value
|
||||
(testing "Find highest value with a single map"
|
||||
(let [data [{:value 5}]]
|
||||
(is (= (utils/find-highest-value data) 5))))
|
||||
|
||||
(testing "Find highest value with multiple maps"
|
||||
(let [data [{:value 5} {:value 10} {:value 3} {:value 7}]]
|
||||
(is (= (utils/find-highest-value data) 10))))
|
||||
|
||||
(testing "Find highest value with negative values"
|
||||
(let [data [{:value -2} {:value -10} {:value -3} {:value -7}]]
|
||||
(is (= (utils/find-highest-value data) -2))))
|
||||
|
||||
(testing "Find highest value with decimal values"
|
||||
(let [data [{:value 3.5} {:value 7.2} {:value 2.9}]]
|
||||
(is (= (utils/find-highest-value data) 7.2))))
|
||||
|
||||
(testing "Find highest value with a large data set"
|
||||
(let [data (vec (for [num (range 1000)] {:value num}))]
|
||||
(is (= (utils/find-highest-value data) 999)))))
|
||||
|
||||
(deftest find-lowest-value
|
||||
(testing "Find lowest value with a single map"
|
||||
(let [data [{:value 5}]]
|
||||
(is (= (utils/find-lowest-value data) 5))))
|
||||
|
||||
(testing "Find lowest value with multiple maps"
|
||||
(let [data [{:value 5} {:value 10} {:value 3} {:value 7}]]
|
||||
(is (= (utils/find-lowest-value data) 3))))
|
||||
|
||||
(testing "Find lowest value with negative values"
|
||||
(let [data [{:value -2} {:value -10} {:value -3} {:value -7}]]
|
||||
(is (= (utils/find-lowest-value data) -10))))
|
||||
|
||||
(testing "Find lowest value with decimal values"
|
||||
(let [data [{:value 3.5} {:value 7.2} {:value 2.9}]]
|
||||
(is (= (utils/find-lowest-value data) 2.9))))
|
||||
|
||||
(testing "Find lowest value with a large data set"
|
||||
(let [data (vec (for [num (range 1000)] {:value num}))]
|
||||
(is (= (utils/find-lowest-value data) 0)))))
|
||||
|
||||
(deftest downsample-data
|
||||
(testing "Downsampling is applied correctly when needed"
|
||||
(let [input-data [1 2 3 4 5 6 7 8 9 10]
|
||||
max-array-size 5
|
||||
expected-output [1 3 5 7 9]]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling is not applied when not needed"
|
||||
(let [input-data [1 2 3 4 5 6 7 8 9 10]
|
||||
max-array-size 10
|
||||
expected-output [1 2 3 4 5 6 7 8 9 10]]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling works with empty input data"
|
||||
(let [input-data []
|
||||
max-array-size 5
|
||||
expected-output []]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling works with max-array-size of 1 (edge case)"
|
||||
(let [input-data [1 2 3 4 5]
|
||||
max-array-size 1
|
||||
expected-output [1]]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling works with large input data and max-array-size (randomized test)"
|
||||
(let [large-data (range 1000)
|
||||
max-array-size 500
|
||||
expected-output (range 0 1000 2)] ; expected-output contains every 2nd element from 0 to 1000
|
||||
(is (= (utils/downsample-data large-data max-array-size) expected-output)))))
|
||||
|
||||
(deftest format-compact-number
|
||||
(testing "Format a whole number less than 1000"
|
||||
(is (= (utils/format-compact-number 567) "567")))
|
||||
|
||||
(testing "Format a whole number exactly 1000"
|
||||
(is (= (utils/format-compact-number 1000) "1k")))
|
||||
|
||||
(testing "Format a whole number greater than 1000"
|
||||
(is (= (utils/format-compact-number 2500) "2.5k")))
|
||||
|
||||
(testing "Format a decimal number less than 1000"
|
||||
(is (= (utils/format-compact-number 123.45) "123.45")))
|
||||
|
||||
(testing "Format a decimal number exactly 1000"
|
||||
(is (= (utils/format-compact-number 1000) "1k")))
|
||||
|
||||
(testing "Format a decimal number greater than 1000"
|
||||
(is (= (utils/format-compact-number 7890.123) "7.89k")))
|
||||
|
||||
(testing "Format a number in millions"
|
||||
(is (= (utils/format-compact-number 123456789) "123.46M")))
|
||||
|
||||
(testing "Format a number in billions"
|
||||
(is (= (utils/format-compact-number 1234567890) "1.23B")))
|
||||
|
||||
(testing "Format a number in trillions"
|
||||
(is (= (utils/format-compact-number 1234567890000) "1.23T"))))
|
||||
|
||||
(deftest calculate-x-axis-labels
|
||||
(testing "Calculate x-axis labels with a small array and fewer elements"
|
||||
(let [data [{:date "2023-01-01"} {:date "2023-01-02"} {:date "2023-01-03"} {:date "2023-01-04"}]]
|
||||
(is (= (utils/calculate-x-axis-labels data 2) '("2023-01-01" "2023-01-03")))))
|
||||
|
||||
(testing "Calculate x-axis labels with a larger array and more elements"
|
||||
(let [data (vec (for [i (range 10)] {:date (str "2023-01-0" (inc i))}))]
|
||||
(is (= (utils/calculate-x-axis-labels data 5)
|
||||
'("2023-01-01" "2023-01-03" "2023-01-05" "2023-01-07" "2023-01-09")))))
|
||||
|
||||
(testing "Calculate x-axis labels with a very small array"
|
||||
(let [data [{:date "2023-01-01"}]]
|
||||
(is (= (utils/calculate-x-axis-labels data 3) '("2023-01-01")))))
|
||||
|
||||
(testing "Calculate x-axis labels with a larger array and a single element"
|
||||
(let [data (vec (for [i (range 10)] {:date (str "2023-01-0" (inc i))}))]
|
||||
(is (= (utils/calculate-x-axis-labels data 1) '("2023-01-01"))))))
|
||||
|
||||
(deftest calculate-y-axis-labels
|
||||
(testing "Calculate y-axis labels with positive values"
|
||||
(is (= (utils/calculate-y-axis-labels 0 10 5) ["0" "10" "20" "30" "40" "50"])))
|
||||
|
||||
(testing "Calculate y-axis labels with negative values"
|
||||
(is (= (utils/calculate-y-axis-labels -20 5 4) ["-20" "-15" "-10" "-5" "0"])))
|
||||
|
||||
(testing "Calculate y-axis labels with decimal step value"
|
||||
(is (= (utils/calculate-y-axis-labels 2.5 0.5 4) ["2.5" "3" "3.5" "4" "4.5"])))
|
||||
|
||||
(testing "Calculate y-axis labels with a single step"
|
||||
(is (= (utils/calculate-y-axis-labels 5 1 1) ["5" "6"])))
|
||||
|
||||
(testing "Calculate y-axis labels with large step value and number of steps"
|
||||
(is (= (utils/calculate-y-axis-labels 100 1000 3) ["100" "1.1k" "2.1k" "3.1k"]))))
|
||||
|
||||
(deftest calculate-rounded-max
|
||||
(testing "Calculate rounded max with a whole number"
|
||||
(is (= (utils/calculate-rounded-max 100) 108)))
|
||||
|
||||
(testing "Calculate rounded max with a decimal number"
|
||||
(is (= (utils/calculate-rounded-max 50.5) 56)))
|
||||
|
||||
(testing "Calculate rounded max with a number already divisible by divisor"
|
||||
(is (= (utils/calculate-rounded-max 108) 116)))
|
||||
|
||||
(testing "Calculate rounded max with a number close to the next divisor"
|
||||
(is (= (utils/calculate-rounded-max 250) 264)))
|
||||
|
||||
(testing "Calculate rounded max with a large number"
|
||||
(is (= (utils/calculate-rounded-max 1000) 1052))))
|
||||
|
||||
(deftest calculate-rounded-min
|
||||
(testing "Calculate rounded min with a whole number"
|
||||
(is (= (utils/calculate-rounded-min 157) 100)))
|
||||
|
||||
(testing "Calculate rounded min with a decimal number"
|
||||
(is (= (utils/calculate-rounded-min 49.8) 40)))
|
||||
|
||||
(testing "Calculate rounded min with a small number"
|
||||
(is (= (utils/calculate-rounded-min 0.007) 0)))
|
||||
|
||||
(testing "Calculate rounded min with a number already rounded"
|
||||
(is (= (utils/calculate-rounded-min 500) 500)))
|
||||
|
||||
(testing "Calculate rounded min with a negative number"
|
||||
(is (= (utils/calculate-rounded-min -63) -68))))
|
||||
|
||||
(deftest format-currency-number-test
|
||||
(testing "Format currency number with comma decimal separator"
|
||||
(is (= (utils/format-currency-number 12345 :comma) "12.345,00"))
|
||||
(is (= (utils/format-currency-number 12345.67 :comma) "12.345,67")))
|
||||
|
||||
(testing "Format currency number with dot decimal separator"
|
||||
(is (= (utils/format-currency-number 12345 :dot) "12,345.00"))
|
||||
(is (= (utils/format-currency-number 12345.67 :dot) "12,345.67"))))
|
||||
@@ -0,0 +1,13 @@
|
||||
(ns quo2.components.graph.wallet-graph.utils)
|
||||
|
||||
(defn find-highest-value
|
||||
[coll]
|
||||
(apply max (map :value coll)))
|
||||
|
||||
(defn downsample-data
|
||||
[data max-array-size]
|
||||
(let [data-size (count data)]
|
||||
(if (> data-size max-array-size)
|
||||
(let [step-size (max (/ data-size max-array-size) 1)]
|
||||
(vec (take-nth step-size data)))
|
||||
data)))
|
||||
@@ -0,0 +1,55 @@
|
||||
(ns quo2.components.graph.wallet-graph.utils-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[quo2.components.graph.wallet-graph.utils :as utils]))
|
||||
|
||||
(deftest find-highest-value
|
||||
(testing "Find highest value with a single map"
|
||||
(let [data [{:value 5}]]
|
||||
(is (= (utils/find-highest-value data) 5))))
|
||||
|
||||
(testing "Find highest value with multiple maps"
|
||||
(let [data [{:value 5} {:value 10} {:value 3} {:value 7}]]
|
||||
(is (= (utils/find-highest-value data) 10))))
|
||||
|
||||
(testing "Find highest value with negative values"
|
||||
(let [data [{:value -2} {:value -10} {:value -3} {:value -7}]]
|
||||
(is (= (utils/find-highest-value data) -2))))
|
||||
|
||||
(testing "Find highest value with decimal values"
|
||||
(let [data [{:value 3.5} {:value 7.2} {:value 2.9}]]
|
||||
(is (= (utils/find-highest-value data) 7.2))))
|
||||
|
||||
(testing "Find highest value with a large data set"
|
||||
(let [data (vec (for [num (range 1000)] {:value num}))]
|
||||
(is (= (utils/find-highest-value data) 999)))))
|
||||
|
||||
(deftest downsample-data
|
||||
(testing "Downsampling is applied correctly when needed"
|
||||
(let [input-data [1 2 3 4 5 6 7 8 9 10]
|
||||
max-array-size 5
|
||||
expected-output [1 3 5 7 9]]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling is not applied when not needed"
|
||||
(let [input-data [1 2 3 4 5 6 7 8 9 10]
|
||||
max-array-size 10
|
||||
expected-output [1 2 3 4 5 6 7 8 9 10]]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling works with empty input data"
|
||||
(let [input-data []
|
||||
max-array-size 5
|
||||
expected-output []]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling works with max-array-size of 1 (edge case)"
|
||||
(let [input-data [1 2 3 4 5]
|
||||
max-array-size 1
|
||||
expected-output [1]]
|
||||
(is (= (utils/downsample-data input-data max-array-size) expected-output))))
|
||||
|
||||
(testing "Downsampling works with large input data and max-array-size (randomized test)"
|
||||
(let [large-data (range 1000)
|
||||
max-array-size 500
|
||||
expected-output (range 0 1000 2)] ;; expected-output contains every 2nd element from 0 to 1000
|
||||
(is (= (utils/downsample-data large-data max-array-size) expected-output)))))
|
||||
@@ -6,9 +6,9 @@
|
||||
[quo2.components.graph.wallet-graph.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.graph.utils :as utils]))
|
||||
[quo2.components.graph.wallet-graph.utils :as utils]))
|
||||
|
||||
(defn- time-frame->max-data-points
|
||||
(defn- max-data-points
|
||||
[time-frame]
|
||||
(case time-frame
|
||||
:empty 0
|
||||
@@ -18,26 +18,17 @@
|
||||
:1-year 365
|
||||
500))
|
||||
|
||||
(defn- get-line-color
|
||||
[customization-color state theme]
|
||||
(let [color-keyword (cond
|
||||
customization-color customization-color
|
||||
(= state :positive) :success
|
||||
:else :danger)]
|
||||
(colors/theme-colors
|
||||
(colors/custom-color color-keyword 50)
|
||||
(colors/custom-color color-keyword 60)
|
||||
theme)))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [data state time-frame customization-color theme]}]
|
||||
(let [max-data-points (time-frame->max-data-points time-frame)
|
||||
[{:keys [data state time-frame theme]}]
|
||||
(let [max-data-points (max-data-points time-frame)
|
||||
data (if (and (not= time-frame :empty) (> (count data) max-data-points))
|
||||
(utils/downsample-data data max-data-points)
|
||||
data)
|
||||
max-value (when-not (= time-frame :empty) (utils/find-highest-value data))
|
||||
width (:width (rn/get-window))
|
||||
line-color (get-line-color customization-color state theme)
|
||||
line-color (if (= state :positive)
|
||||
(colors/theme-colors colors/success-50 colors/success-60 theme)
|
||||
(colors/theme-colors colors/danger-50 colors/danger-60 theme))
|
||||
gradient-colors [(colors/alpha line-color 0.1) (colors/alpha line-color 0)]
|
||||
fill-color (colors/theme-colors colors/white colors/neutral-95)]
|
||||
(if (= time-frame :empty)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def left-style
|
||||
(def left
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
@@ -45,7 +45,7 @@
|
||||
:justify-content :center
|
||||
:align-items :flex-start})
|
||||
|
||||
(def right-style
|
||||
(def right
|
||||
{:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
@@ -176,7 +176,7 @@
|
||||
{:style content
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style left-style
|
||||
{:style left
|
||||
:on-layout (handle-layout :left get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
@@ -194,7 +194,7 @@
|
||||
:component title-component}]]
|
||||
|
||||
[rn/view
|
||||
{:style right-style
|
||||
{:style right
|
||||
:on-layout (handle-layout :right get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
|
||||
@@ -9,4 +9,5 @@
|
||||
{:placeholder "Your Name"
|
||||
:on-press event}])
|
||||
(h/fire-event :press (h/get-by-label-text :select-profile-picture-button))
|
||||
(h/was-called-times event 1))))
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
(ns quo2.components.inputs.profile-input.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
(:require [react-native.platform :as platform]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
[customization-color]
|
||||
{:background-color (colors/custom-color customization-color 50 40)
|
||||
:padding-horizontal 12
|
||||
:padding-top 12
|
||||
:padding-bottom 10
|
||||
:padding-bottom (if platform/ios? 10 0)
|
||||
:border-radius 16
|
||||
:flex 1})
|
||||
|
||||
|
||||
@@ -31,11 +31,10 @@
|
||||
:borderRadius 12}]}
|
||||
[user-avatar/user-avatar
|
||||
(assoc image-picker-props
|
||||
:customization-color customization-color
|
||||
:static? true
|
||||
:status-indicator? false
|
||||
:full-name (if (seq full-name) full-name placeholder)
|
||||
:size :medium)]]
|
||||
:static? true
|
||||
:status-indicator? false
|
||||
:full-name (if (seq full-name) full-name placeholder)
|
||||
:size :medium)]]
|
||||
[buttons/button
|
||||
{:accessibility-label :select-profile-picture-button
|
||||
:type :grey
|
||||
@@ -46,7 +45,7 @@
|
||||
:container-style style/button
|
||||
:inner-style style/button-inner} :i/camera]]
|
||||
[rn/view {:style style/input-container}
|
||||
[title-input/view
|
||||
[title-input/title-input
|
||||
(merge title-input-props
|
||||
{:blur? true
|
||||
:placeholder placeholder
|
||||
|
||||
@@ -2,31 +2,39 @@
|
||||
(:require [quo2.components.inputs.title-input.view :as title-input]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "input -> title-input component"
|
||||
(h/describe "profile: title-input"
|
||||
(h/test "renders empty"
|
||||
(h/render [title-input/view {:value ""}])
|
||||
(h/is-truthy (h/query-by-label-text :profile-title-input)))
|
||||
(h/render [title-input/title-input
|
||||
{:value ""
|
||||
:on-change-text (h/mock-fn)}])
|
||||
(-> (js/expect (h/get-by-label-text :profile-title-input))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "empty text renders with max length digits and 00"
|
||||
(h/render [title-input/view
|
||||
{:value ""
|
||||
:max-length 24}])
|
||||
(h/fire-event :on-focus (h/query-by-label-text :profile-title-input))
|
||||
(h/wait-for #(h/is-truthy (h/query-by-text "00")))
|
||||
(h/is-truthy (h/query-by-text "/24")))
|
||||
(h/render [title-input/title-input
|
||||
{:value ""
|
||||
:max-length 24
|
||||
:on-change-text (h/mock-fn)}])
|
||||
(-> (js/expect (h/get-by-text "00"))
|
||||
(.toBeTruthy))
|
||||
(-> (js/expect (h/get-by-text "/24"))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "renders with max length digits and character count"
|
||||
(h/render [title-input/view
|
||||
{:default-value "abc"
|
||||
:max-length 24} "abc"])
|
||||
(h/fire-event :on-focus (h/query-by-label-text :profile-title-input))
|
||||
(h/wait-for #(h/is-truthy (h/query-by-text "03")))
|
||||
(h/is-truthy (h/query-by-text "/24")))
|
||||
(h/render [title-input/title-input
|
||||
{:default-value "abc"
|
||||
:max-length 24
|
||||
:on-change-text (h/mock-fn)} "abc"])
|
||||
(-> (js/expect (h/get-by-text "03"))
|
||||
(.toBeTruthy))
|
||||
(-> (js/expect (h/get-by-text "/24"))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "text updates on change"
|
||||
(let [on-change-text (h/mock-fn)]
|
||||
(h/render [title-input/view
|
||||
(h/render [title-input/title-input
|
||||
{:value "mock text"
|
||||
:on-change-text on-change-text}])
|
||||
(h/fire-event :change-text (h/get-by-label-text :profile-title-input) "mock-text-new")
|
||||
(h/was-called on-change-text))))
|
||||
(-> (js/expect on-change-text)
|
||||
(.toHaveBeenCalled)))))
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-60 theme)))
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-60 theme))
|
||||
)
|
||||
|
||||
(defn get-placeholder-color
|
||||
[blur? theme]
|
||||
@@ -14,7 +15,13 @@
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30 theme)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
|
||||
|
||||
(defn get-char-count-color
|
||||
(defn- get-disabled-color
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
|
||||
|
||||
(defn- get-char-count-color
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40)
|
||||
@@ -31,23 +38,21 @@
|
||||
(def text-input-container {:flex 1})
|
||||
|
||||
(defn title-text
|
||||
[theme]
|
||||
[disabled? blur? theme]
|
||||
{:text-align-vertical :bottom
|
||||
:padding 0
|
||||
:color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
||||
:color (if disabled?
|
||||
(get-disabled-color blur? theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme))})
|
||||
|
||||
(defn char-count
|
||||
[blur? theme]
|
||||
{:color (get-char-count-color blur? theme)})
|
||||
|
||||
(defn container
|
||||
[disabled?]
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:opacity (if disabled? 0.3 1)
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(defn counter-container
|
||||
[focused?]
|
||||
{:padding-top (if focused? 12 9)
|
||||
:padding-bottom (if focused? 2 3)})
|
||||
(def counter-container
|
||||
{:padding-top 8})
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
[quo2.components.markdown.text :as text]
|
||||
[reagent.core :as reagent]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as quo.theme]
|
||||
[quo2.components.icon :as icon]))
|
||||
[quo2.theme :as theme]))
|
||||
|
||||
(defn- pad-0
|
||||
[value]
|
||||
@@ -13,7 +12,7 @@
|
||||
(str 0 value)
|
||||
value))
|
||||
|
||||
(defn- view-internal
|
||||
(defn- title-input-internal
|
||||
[{:keys [blur?
|
||||
on-change-text
|
||||
auto-focus
|
||||
@@ -27,24 +26,23 @@
|
||||
default-value ""}}]
|
||||
(let [focused? (reagent/atom auto-focus)
|
||||
value (reagent/atom default-value)
|
||||
input-ref (atom nil)
|
||||
on-change (fn [v]
|
||||
(reset! value v)
|
||||
(when on-change-text
|
||||
(on-change-text v)))]
|
||||
(fn [{:keys [customization-color disabled?]}]
|
||||
[rn/view
|
||||
{:style (merge (style/container disabled?) container-style)}
|
||||
{:style (merge style/container container-style)}
|
||||
[rn/view {:style style/text-input-container}
|
||||
[rn/text-input
|
||||
{:style
|
||||
(text/text-style
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style (style/title-text theme)})
|
||||
:style (style/title-text disabled? blur? theme)})
|
||||
:default-value default-value
|
||||
:accessibility-label :profile-title-input
|
||||
:keyboard-appearance (quo.theme/theme-value :light :dark theme)
|
||||
:keyboard-appearance (theme/theme-value :light :dark theme)
|
||||
:on-focus #(swap! focused? (constantly true))
|
||||
:on-blur #(swap! focused? (constantly false))
|
||||
:auto-focus auto-focus
|
||||
@@ -53,30 +51,24 @@
|
||||
:editable (not disabled?)
|
||||
:max-length max-length
|
||||
:placeholder placeholder
|
||||
:ref #(reset! input-ref %)
|
||||
:selection-color (style/get-selection-color customization-color blur? theme)
|
||||
:placeholder-text-color (if @focused?
|
||||
(style/get-focused-placeholder-color blur? theme)
|
||||
(style/get-placeholder-color blur? theme))}]]
|
||||
[rn/view
|
||||
{:style (style/counter-container @focused?)}
|
||||
(if @focused?
|
||||
[text/text
|
||||
[text/text
|
||||
{:style (style/char-count blur? theme)
|
||||
:size :paragraph-2}
|
||||
(pad-0
|
||||
(str
|
||||
(count @value)))]
|
||||
[text/text
|
||||
{:style (style/char-count blur? theme)
|
||||
:size :paragraph-2}
|
||||
(str "/"
|
||||
(pad-0
|
||||
(str max-length)))]]
|
||||
[rn/pressable
|
||||
{:on-press #(when-not disabled?
|
||||
(.focus ^js @input-ref))}
|
||||
[icon/icon :i/edit {:color (style/get-char-count-color blur? theme)}]])]])))
|
||||
{:style style/counter-container}
|
||||
[text/text
|
||||
[text/text
|
||||
{:style (style/char-count blur? theme)
|
||||
:size :paragraph-2}
|
||||
(pad-0
|
||||
(str
|
||||
(count @value)))]
|
||||
[text/text
|
||||
{:style (style/char-count blur? theme)
|
||||
:size :paragraph-2}
|
||||
(str "/"
|
||||
(pad-0
|
||||
(str max-length)))]]]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def title-input (theme/with-theme title-input-internal))
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
(ns quo2.components.list-items.channel
|
||||
(:require [quo2.components.avatars.channel-avatar.view :as channel-avatar]
|
||||
[quo2.components.common.unread-grey-dot.view :as unread-grey-dot]
|
||||
[quo2.components.counter.counter.view :as counter]
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private custom-props
|
||||
[:name :locked? :mentions-count :unread-messages?
|
||||
:muted? :is-active-channel? :emoji :channel-color])
|
||||
|
||||
(defn list-item
|
||||
[{:keys [locked? mentions-count unread-messages?
|
||||
muted? is-active-channel? emoji channel-color
|
||||
default-color]
|
||||
:as props}]
|
||||
(let [channel-color (or channel-color default-color)
|
||||
standard-props (apply dissoc props custom-props)
|
||||
name-text (:name props)]
|
||||
[rn/touchable-opacity standard-props
|
||||
[rn/view
|
||||
{:style (cond-> {:height 48
|
||||
:border-radius 12
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:padding-left 12
|
||||
:padding-right 12}
|
||||
is-active-channel? (assoc :background-color
|
||||
(colors/theme-alpha channel-color 0.05 0.05)))}
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:justify-content :flex-start
|
||||
:align-items :center}
|
||||
:accessible true
|
||||
:accessibility-label :chat-name-text}
|
||||
[channel-avatar/view
|
||||
{:size :size/l
|
||||
:locked? locked?
|
||||
:full-name (:name props)
|
||||
:customization-color channel-color
|
||||
:emoji emoji}]
|
||||
[quo2.text/text
|
||||
{:style (cond-> {:margin-left 12}
|
||||
(and (not locked?) muted?)
|
||||
(assoc :color (colors/theme-colors colors/neutral-40 colors/neutral-60)))
|
||||
:weight :medium
|
||||
:size :paragraph-1}
|
||||
(str "# " name-text)]]
|
||||
(when-not locked?
|
||||
[rn/view {:style {:height 20 :justify-content :center}}
|
||||
(cond
|
||||
muted?
|
||||
[quo2.icons/icon :i/muted
|
||||
{:size 20
|
||||
:color colors/neutral-40
|
||||
:container-style {:margin-right 1 :margin-top 2}}]
|
||||
|
||||
(pos? (int mentions-count))
|
||||
[rn/view {:style {:margin-right 2 :margin-top 2}}
|
||||
[counter/view {:customization-color channel-color}
|
||||
mentions-count]]
|
||||
|
||||
unread-messages?
|
||||
[unread-grey-dot/unread-grey-dot :unviewed-messages-public])])]]))
|
||||
@@ -1,44 +0,0 @@
|
||||
(ns quo2.components.list-items.channel.component-spec
|
||||
(:require [test-helpers.component :as h]
|
||||
[quo2.components.list-items.channel.view :as channel]))
|
||||
|
||||
(h/describe "list-items/channel Component"
|
||||
(h/test "default render"
|
||||
(h/render [channel/view {:name "general"}])
|
||||
(h/is-truthy (h/query-by-label-text :channel-list-item)))
|
||||
|
||||
(h/test "with name & emoji"
|
||||
(h/render [channel/view
|
||||
{:name "general"
|
||||
:emoji "👋"}])
|
||||
(h/is-truthy (h/query-by-text "# general"))
|
||||
(h/is-truthy (h/query-by-text "👋")))
|
||||
|
||||
(h/test "notification & mentions count"
|
||||
(h/render [channel/view
|
||||
{:name "general"
|
||||
:mentions-count 10
|
||||
:notification :mention}])
|
||||
(h/is-truthy (h/query-by-text "10")))
|
||||
|
||||
(h/test "unread indicator"
|
||||
(h/render [channel/view
|
||||
{:name "general"
|
||||
:notification :notification}])
|
||||
(h/is-truthy (h/query-by-label-text :unviewed-messages-public)))
|
||||
|
||||
(h/test "on-press event"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [channel/view
|
||||
{:name "general"
|
||||
:on-press on-press}])
|
||||
(h/fire-event :press (h/query-by-label-text :channel-list-item))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "on-long-press event"
|
||||
(let [on-long-press (h/mock-fn)]
|
||||
(h/render [channel/view
|
||||
{:name "general"
|
||||
:on-long-press on-long-press}])
|
||||
(h/fire-event :long-press (h/query-by-label-text :channel-list-item))
|
||||
(h/was-called on-long-press))))
|
||||
@@ -1,50 +0,0 @@
|
||||
(ns quo2.components.list-items.channel.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn- get-label-color
|
||||
[notification theme]
|
||||
(let [colors {:notification (colors/theme-colors colors/neutral-100
|
||||
colors/white
|
||||
theme)
|
||||
:mention (colors/theme-colors colors/neutral-100
|
||||
colors/white
|
||||
theme)
|
||||
:mute (colors/theme-colors colors/neutral-40
|
||||
colors/neutral-60
|
||||
theme)
|
||||
:default (colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)}]
|
||||
(colors (or notification :default))))
|
||||
|
||||
(defn mute-notification-icon-color
|
||||
[theme]
|
||||
(colors/theme-colors colors/neutral-40
|
||||
colors/neutral-60
|
||||
theme))
|
||||
|
||||
(defn container
|
||||
[pressed? customization-color theme]
|
||||
{:height 48
|
||||
:border-radius 12
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 8
|
||||
:align-items :center
|
||||
:overflow :hidden
|
||||
:background-color (if pressed?
|
||||
(colors/theme-colors
|
||||
(colors/custom-color customization-color 50 5)
|
||||
(colors/custom-color customization-color 60 5)
|
||||
theme)
|
||||
:transparent)
|
||||
:flex-direction :row})
|
||||
|
||||
(defn label
|
||||
[notification theme]
|
||||
{:margin-horizontal 12
|
||||
:color (get-label-color notification theme)
|
||||
:flex 1})
|
||||
|
||||
(defn counter
|
||||
[mentions]
|
||||
{:margin-horizontal (if (= (count (str mentions)) 1) 2 0)})
|
||||
@@ -1,63 +0,0 @@
|
||||
(ns quo2.components.list-items.channel.view
|
||||
(:require [quo2.components.list-items.channel.style :as style]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.avatars.channel-avatar.view :as channel-avatar]
|
||||
[quo2.components.markdown.text :as quo.text]
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.counter.counter.view :as counter]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- view-internal
|
||||
"Options:
|
||||
- notification - (nil/:notification/:mention/:mute, default: nil):
|
||||
- :notification - Display a grey dot.
|
||||
- :mention - Display a counter.
|
||||
- :mute - Display a mute icon.
|
||||
- locked? - (nil/boolean, default: nil):
|
||||
- When true, display a locked icon.
|
||||
- When false, display an unlocked icon.
|
||||
- mentions-count - (default: nil) - Number of mentions to display in the counter with :mention notification.
|
||||
- customization-color - (default: nil) - Community color.
|
||||
- emoji - (string, default: nil):
|
||||
- Emoji to be displayed on the channel avatar.
|
||||
- If blank, initials of the channel name are displayed.
|
||||
- name - (string, default: nil) - Channel name.
|
||||
- on-press - (function, default: nil) - Function called when the component is pressed.
|
||||
- on-long-press - (function, default: nil) - Function called when the component is long pressed.
|
||||
- theme - Theme value from with-theme HOC"
|
||||
[]
|
||||
(let [pressed? (reagent/atom false)]
|
||||
(fn [{:keys [notification locked? mentions-count customization-color emoji name on-press
|
||||
on-long-press theme]}]
|
||||
[rn/pressable
|
||||
{:style (style/container @pressed? customization-color theme)
|
||||
:accessibility-label :channel-list-item
|
||||
:on-press on-press
|
||||
:on-long-press on-long-press
|
||||
:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)}
|
||||
[channel-avatar/view
|
||||
{:size :size/l
|
||||
:locked? locked?
|
||||
:full-name name
|
||||
:customization-color customization-color
|
||||
:emoji emoji}]
|
||||
[quo.text/text
|
||||
{:style (style/label notification theme)
|
||||
:weight :medium
|
||||
:size :paragraph-1} (str "# " name)]
|
||||
(when-not locked?
|
||||
(condp = notification
|
||||
:mute [quo2.icons/icon :i/muted
|
||||
{:color (style/mute-notification-icon-color theme)}]
|
||||
:mention [counter/view
|
||||
{:customization-color customization-color
|
||||
:container-style (style/counter mentions-count)}
|
||||
mentions-count]
|
||||
:notification [quo2.icons/icon :i/notification
|
||||
{:color (style/mute-notification-icon-color theme)
|
||||
:accessibility-label :unviewed-messages-public}]
|
||||
nil))])))
|
||||
|
||||
(def view (theme/with-theme view-internal))
|
||||
@@ -21,9 +21,7 @@
|
||||
|
||||
;; Standlone message skeleton
|
||||
(defn- f-message-skeleton
|
||||
{:deprecated "quo2.components.loaders.skeleton-list.view should be used instead"}
|
||||
[]
|
||||
|
||||
(let [color (colors/theme-colors colors/neutral-5 colors/neutral-70)
|
||||
loading-color (colors/theme-colors colors/neutral-10 colors/neutral-60)
|
||||
content-width (rand-nth message-content-width)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
[{:keys [primary-name secondary-name style short-chat-key time-str contact? verified? untrustworthy?
|
||||
muted? size]
|
||||
:or {size 13}}]
|
||||
[rn/view {:style (merge style/container style {:height (if (= size 15) 21.75 18.2)})}
|
||||
[rn/view {:style (merge style/container style)}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size (if (= size 15) :paragraph-1 :paragraph-2)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
(ns quo2.components.messages.system-message
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.icon-avatar :as icon-avatar]
|
||||
(:require [quo2.components.avatars.icon-avatar :as icon-avatar]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.messages.author.view :as author]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
[utils.i18n :as i18n]
|
||||
[quo2.theme :as quo.theme]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(defn text-color
|
||||
[theme]
|
||||
@@ -14,24 +15,24 @@
|
||||
|
||||
(defn time-color
|
||||
[theme]
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme))
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))
|
||||
|
||||
(defn sm-icon
|
||||
[{:keys [icon color opacity]}]
|
||||
[rn/view
|
||||
{:margin-right 8}
|
||||
[icon-avatar/icon-avatar
|
||||
{:size :size/s-32
|
||||
{:size :medium
|
||||
:icon icon
|
||||
:color color
|
||||
:opacity opacity}]])
|
||||
|
||||
(defn sm-timestamp
|
||||
[timestamp theme]
|
||||
[rn/view {:margin-left 8}
|
||||
[timestamp]
|
||||
[rn/view {:margin-left 8 :margin-top 2}
|
||||
[text/text
|
||||
{:size :label
|
||||
:style {:color (time-color theme)
|
||||
:style {:color (time-color :time)
|
||||
:text-transform :none}}
|
||||
timestamp]])
|
||||
|
||||
@@ -47,72 +48,66 @@
|
||||
|
||||
(defn split-text
|
||||
[label theme add-pred?]
|
||||
(let [color (text-color theme)
|
||||
label-vector (map-indexed vector (string/split label " "))]
|
||||
[rn/view {:style {:flex-direction :row :flex-shrink 0 :align-items :center}}
|
||||
(let [color (text-color theme)]
|
||||
[:<>
|
||||
(when add-pred?
|
||||
[text/text {} " "])
|
||||
(for [[indx item] label-vector]
|
||||
(for [[indx item] (map-indexed vector (string/split label " "))]
|
||||
^{:key indx}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color color
|
||||
:margin-right (if (= indx (dec (count label-vector)))
|
||||
0
|
||||
3)}}
|
||||
:margin-right 3}}
|
||||
item])]))
|
||||
|
||||
(defn system-message-base
|
||||
[{:keys [icon]} child]
|
||||
[{:keys [icon timestamp]} child]
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :center}
|
||||
:flex 1}
|
||||
[sm-icon icon]
|
||||
[rn/view
|
||||
{:align-self :center
|
||||
:flex-direction :row
|
||||
:margin-right 40 ;; dirty hack, flexbox won't work as expected
|
||||
:flex 1}
|
||||
child]])
|
||||
child
|
||||
[sm-timestamp timestamp]]])
|
||||
|
||||
(defn system-message-deleted-internal
|
||||
[{:keys [label child theme timestamp]}]
|
||||
[system-message-base
|
||||
{:icon {:icon :i/delete
|
||||
:color :danger
|
||||
:opacity 5}}
|
||||
[rn/view {:style {:flex-direction :row :align-items :center}}
|
||||
(if child
|
||||
child
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (text-color theme)}}
|
||||
(or label (i18n/label :t/message-deleted))])
|
||||
[sm-timestamp timestamp theme]]])
|
||||
{:icon {:icon :i/delete
|
||||
:color :danger
|
||||
:opacity 5}
|
||||
:timestamp timestamp}
|
||||
(if child
|
||||
child
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (text-color theme)}}
|
||||
(or label (i18n/label :t/message-deleted))])])
|
||||
|
||||
(def system-message-deleted (quo.theme/with-theme system-message-deleted-internal))
|
||||
|
||||
(defn system-message-contact-internal
|
||||
[{:keys [display-name photo-path customization-color theme timestamp]} label icon]
|
||||
[system-message-base
|
||||
{:icon {:icon icon
|
||||
:color (or customization-color :primary)
|
||||
:opacity 5}}
|
||||
{:icon {:icon icon
|
||||
:color (or customization-color :primary)
|
||||
:opacity 5}
|
||||
:timestamp timestamp}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:flex-shrink 1
|
||||
:flex-wrap :nowrap}
|
||||
[rn/view {:flex-direction :row :align-items :center :flex-shrink 1}
|
||||
:flex-wrap :wrap}
|
||||
[rn/view {:flex-direction :row :align-items :center}
|
||||
[sm-user-avatar display-name photo-path]
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:style {:flex-shrink 1}
|
||||
:size :paragraph-2}
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
display-name]]
|
||||
[split-text label theme true]
|
||||
[sm-timestamp timestamp theme]]])
|
||||
[split-text label theme true]]])
|
||||
|
||||
(def system-message-contact (quo.theme/with-theme system-message-contact-internal))
|
||||
|
||||
@@ -132,47 +127,38 @@
|
||||
(defn system-message-contact-request-internal
|
||||
[{:keys [display-name photo-path customization-color theme timestamp incoming?]}]
|
||||
[system-message-base
|
||||
{:icon {:icon :i/add-user
|
||||
:color (or customization-color :primary)
|
||||
:opacity 5}}
|
||||
{:icon {:icon :i/add-user
|
||||
:color (or customization-color :primary)
|
||||
:opacity 5}
|
||||
:timestamp timestamp}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:flex-shrink 1
|
||||
:flex-wrap :nowrap}
|
||||
:flex-wrap :wrap}
|
||||
(when-not incoming? [split-text "Contact request sent to" theme false])
|
||||
[rn/view {:flex-direction :row :align-items :center :flex-shrink 1}
|
||||
[rn/view {:flex-direction :row :align-items :center}
|
||||
[sm-user-avatar display-name photo-path]
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:style {:flex-shrink 1}
|
||||
:size :paragraph-2}
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
display-name]]
|
||||
(when incoming? [split-text "sent you a contact request" theme true])
|
||||
[sm-timestamp timestamp theme]]])
|
||||
(when incoming? [split-text "sent you a contact request" theme true])]])
|
||||
|
||||
(def system-message-contact-request (quo.theme/with-theme system-message-contact-request-internal))
|
||||
|
||||
(defn system-message-pinned-internal
|
||||
[{:keys [pinned-by child customization-color theme timestamp]}]
|
||||
[system-message-base
|
||||
{:icon {:icon :i/pin
|
||||
:color (or customization-color :primary)
|
||||
:opacity 5}}
|
||||
[rn/view {:style {:flex 1}}
|
||||
{:icon {:icon :i/pin
|
||||
:color (or customization-color :primary)
|
||||
:opacity 5}
|
||||
:timestamp timestamp}
|
||||
[rn/view
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:flex-wrap :nowrap}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:style {:flex-shrink 1}
|
||||
:size :paragraph-2}
|
||||
pinned-by]
|
||||
[split-text (i18n/label :pinned-a-message) theme true]
|
||||
[sm-timestamp timestamp theme]]
|
||||
:flex-wrap :wrap}
|
||||
[author/author {:primary-name pinned-by}]
|
||||
[split-text (i18n/label :pinned-a-message) theme true]]
|
||||
(when child child)]])
|
||||
|
||||
(def system-message-pinned (quo.theme/with-theme system-message-pinned-internal))
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
(ns quo2.components.navigation.top-nav.component-spec
|
||||
(:require [quo2.components.navigation.top-nav.view :as top-nav]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Top Nav component"
|
||||
(h/test "Renders default"
|
||||
(h/render [top-nav/view])
|
||||
(h/is-truthy (h/get-by-label-text :open-scanner-button))
|
||||
(h/is-truthy (h/get-by-label-text :open-activity-center-button))
|
||||
(h/is-truthy (h/get-by-label-text :show-qr-button))
|
||||
(h/is-truthy (h/get-by-label-text :open-profile)))
|
||||
|
||||
(h/test "On press works for all buttons and avatar"
|
||||
(let [avatar-on-press (h/mock-fn)
|
||||
scan-on-press (h/mock-fn)
|
||||
activity-center-on-press (h/mock-fn)
|
||||
qr-code-on-press (h/mock-fn)]
|
||||
|
||||
(h/render [top-nav/view
|
||||
{:avatar-on-press avatar-on-press
|
||||
:scan-on-press scan-on-press
|
||||
:activity-center-on-press activity-center-on-press
|
||||
:qr-code-on-press qr-code-on-press}])
|
||||
|
||||
(h/fire-event :press (h/get-by-label-text :open-scanner-button))
|
||||
(h/was-called scan-on-press)
|
||||
|
||||
(h/fire-event :press (h/get-by-label-text :open-activity-center-button))
|
||||
(h/was-called activity-center-on-press)
|
||||
|
||||
(h/fire-event :press (h/get-by-label-text :show-qr-button))
|
||||
(h/was-called qr-code-on-press)
|
||||
|
||||
(h/fire-event :press (h/get-by-label-text :open-profile))
|
||||
(h/was-called avatar-on-press))))
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
(ns quo2.components.navigation.top-nav.style)
|
||||
|
||||
(defn unread-indicator
|
||||
[unread-count max-value]
|
||||
(let [right-offset (cond
|
||||
(> unread-count max-value)
|
||||
-14
|
||||
;; Greater than 9 means we'll need 2 digits to represent
|
||||
;; the text.
|
||||
(> unread-count 9)
|
||||
-10
|
||||
:else -6)]
|
||||
{:position :absolute
|
||||
:top -6
|
||||
:right right-offset
|
||||
:z-index 4}))
|
||||
|
||||
(def unread-dot
|
||||
{:position :absolute
|
||||
:top -2
|
||||
:bottom 0
|
||||
:right 0
|
||||
:left 38})
|
||||
|
||||
(def right-section
|
||||
{:flex-direction :row})
|
||||
|
||||
(def top-nav-container
|
||||
{:height 56})
|
||||
|
||||
(def top-nav-inner-container
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center})
|
||||
@@ -1,166 +0,0 @@
|
||||
(ns quo2.components.navigation.top-nav.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.counter.counter.view :as counter]
|
||||
[quo2.components.navigation.top-nav.style :as style]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[quo2.theme :as quo.theme]
|
||||
[quo2.components.common.notification-dot.view :as notification-dot]))
|
||||
|
||||
(def notification-dot-hole
|
||||
[{:x 37
|
||||
:y -2
|
||||
:width 9
|
||||
:height 9
|
||||
:borderRadius 4}])
|
||||
|
||||
(defn unread-counter-hole
|
||||
[notification-count]
|
||||
(let [x (case (count (str notification-count))
|
||||
(1 2) 33
|
||||
29)
|
||||
width (case (count (str notification-count))
|
||||
1 16
|
||||
2 20
|
||||
28)]
|
||||
(if (pos? (js/Number notification-count))
|
||||
[{:x x
|
||||
:y -5
|
||||
:width width
|
||||
:height 16
|
||||
:borderRadius 6}]
|
||||
[])))
|
||||
|
||||
(defn- get-button-common-props
|
||||
[{:keys [jump-to? theme blur?]}]
|
||||
{:icon-only? true
|
||||
:size 32
|
||||
:container-style {:margin-left 12}
|
||||
:type (cond
|
||||
jump-to? :black
|
||||
(and (not blur?) (= :dark theme)) :dark-grey
|
||||
:else :grey)
|
||||
:background (when blur? :blur)})
|
||||
|
||||
(defn- unread-indicator
|
||||
[{:keys [notification-count max-value customization-color type]}]
|
||||
(when (pos? notification-count)
|
||||
[counter/view
|
||||
{:accessibility-label :activity-center-unread-count
|
||||
:type type
|
||||
:customization-color customization-color
|
||||
:container-style (style/unread-indicator notification-count
|
||||
max-value)}
|
||||
notification-count]))
|
||||
|
||||
(defn unread-dot
|
||||
[{:keys [customization-color blur? notification]}]
|
||||
[notification-dot/view
|
||||
{:style style/unread-dot
|
||||
:blur? blur?
|
||||
:customization-color (when (= notification :notification) customization-color)}])
|
||||
|
||||
(defn notification-highlight
|
||||
[{:keys [notification notification-count
|
||||
max-unread-notifications customization-color]
|
||||
:as props}]
|
||||
(case notification
|
||||
(:seen :notification) [unread-dot props]
|
||||
(:mention :mention-seen) [unread-indicator
|
||||
{:type (if (= notification :mention-seen) :grey :default)
|
||||
:notification-count notification-count
|
||||
:max-value max-unread-notifications
|
||||
:customization-color customization-color}]
|
||||
[:<>]))
|
||||
|
||||
(defn- left-section
|
||||
[{:keys [avatar-props on-press customization-color]}]
|
||||
[rn/touchable-without-feedback {:on-press on-press}
|
||||
[rn/view
|
||||
{:accessibility-label :open-profile}
|
||||
[user-avatar/user-avatar
|
||||
(merge {:status-indicator? true
|
||||
:ring? true
|
||||
:customization-color customization-color
|
||||
:size :small}
|
||||
avatar-props)]]])
|
||||
|
||||
(defn- right-section
|
||||
[{:keys [theme
|
||||
jump-to?
|
||||
blur?
|
||||
notification
|
||||
notification-count
|
||||
activity-center-on-press
|
||||
scan-on-press
|
||||
qr-code-on-press
|
||||
for-qa-only-cellular-network
|
||||
for-qa-only-no-network
|
||||
for-qa-only-network-type]
|
||||
:as props}]
|
||||
(let [button-common-props (get-button-common-props {:theme theme
|
||||
:jump-to? jump-to?
|
||||
:blur? blur?})]
|
||||
[rn/view {:style style/right-section}
|
||||
(when (= for-qa-only-network-type "cellular")
|
||||
[button/button
|
||||
(merge (dissoc button-common-props :icon-only?)
|
||||
for-qa-only-cellular-network)
|
||||
"🦄"])
|
||||
(when (= for-qa-only-network-type "none")
|
||||
[button/button
|
||||
(merge (dissoc button-common-props :icon-only?)
|
||||
for-qa-only-no-network)
|
||||
"💀"])
|
||||
[button/button
|
||||
(assoc button-common-props :accessibility-label :open-scanner-button :on-press scan-on-press)
|
||||
:i/scan]
|
||||
[button/button
|
||||
(merge button-common-props
|
||||
{:accessibility-label :show-qr-button
|
||||
:on-press qr-code-on-press})
|
||||
:i/qr-code]
|
||||
[rn/view
|
||||
[hole-view/hole-view
|
||||
{:key (hash (str notification notification-count))
|
||||
:holes (case notification
|
||||
(:seen :notification) notification-dot-hole
|
||||
(:mention :mention-seen) (unread-counter-hole notification-count)
|
||||
[])}
|
||||
[button/button
|
||||
(merge button-common-props
|
||||
{:accessibility-label :open-activity-center-button
|
||||
:on-press activity-center-on-press})
|
||||
:i/activity-center]]
|
||||
[notification-highlight props]]]))
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [avatar-on-press avatar-props customization-color container-style] :as props}]
|
||||
[rn/view {:style (merge style/top-nav-container container-style)}
|
||||
[rn/view {:style style/top-nav-inner-container}
|
||||
[left-section
|
||||
{:avatar-props avatar-props
|
||||
:on-press avatar-on-press
|
||||
:customization-color customization-color}]
|
||||
[right-section (dissoc props :avatar-props :avatar-on-press)]]])
|
||||
|
||||
(def view
|
||||
":container-style style map merged with outer view for margins/paddings
|
||||
:customization-color custom colors
|
||||
:blur? true/false
|
||||
:jump-to? true/false
|
||||
:theme :light/:dark
|
||||
:notification :mention/:seen/:notification (TODO :mention-seen temporarily used while resolving https://github.com/status-im/status-mobile/issues/17102 )
|
||||
:avatar-props qu2/user-avatar props
|
||||
:avatar-on-press callback
|
||||
:scan-on-press callback
|
||||
:activity-center-on-press callback
|
||||
:qr-code-on-press callback
|
||||
:notification-count number
|
||||
:max-unread-notifications used to specify max number for counter
|
||||
:for-qa-only-cellular-network used for testing purposed
|
||||
:for-qa-only-no-network used for testing purposed
|
||||
:for-qa-only-network-type used for testing purposed
|
||||
"
|
||||
(quo.theme/with-theme view-internal))
|
||||
@@ -11,7 +11,7 @@
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]))
|
||||
|
||||
(defn- f-profile-card-component
|
||||
[{:keys [keycard-account? profile-picture name
|
||||
[{:keys [keycard-account? profile-picture name hash
|
||||
customization-color emoji-hash on-options-press
|
||||
show-emoji-hash? show-options-button? show-user-hash?
|
||||
show-logged-in? on-card-press login-card? last-item? card-style]
|
||||
@@ -24,8 +24,7 @@
|
||||
login-card? false
|
||||
last-item? false
|
||||
card-style {:padding-horizontal 20
|
||||
:flex 1}}
|
||||
:as args}]
|
||||
:flex 1}}}]
|
||||
(let [{:keys [width]} (rn/get-window)
|
||||
padding-bottom (cond
|
||||
login-card? 38
|
||||
@@ -95,8 +94,7 @@
|
||||
(when show-user-hash?
|
||||
[text/text
|
||||
{:weight :monospace
|
||||
:style style/user-hash}
|
||||
(:hash args)])
|
||||
:style style/user-hash} hash])
|
||||
(when (and show-emoji-hash? emoji-hash)
|
||||
[text/text
|
||||
{:weight :monospace
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
:linear))
|
||||
|
||||
(defn animate-linear-with-delay
|
||||
[shared-value value duration delay-ms]
|
||||
[shared-value value duration delay]
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
shared-value
|
||||
value
|
||||
duration
|
||||
:linear
|
||||
delay-ms))
|
||||
delay))
|
||||
|
||||
(defn animate-linear-with-delay-loop
|
||||
[shared-value value duration delay-ms]
|
||||
[shared-value value duration delay]
|
||||
(reanimated/animate-shared-value-with-delay-repeat
|
||||
shared-value
|
||||
value
|
||||
duration
|
||||
:linear
|
||||
delay-ms
|
||||
delay
|
||||
-1))
|
||||
|
||||
(defn animate-easing
|
||||
@@ -37,13 +37,13 @@
|
||||
:easing1))
|
||||
|
||||
(defn animate-easing-with-delay
|
||||
[shared-value value duration delay-ms]
|
||||
[shared-value value duration delay]
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
shared-value
|
||||
value
|
||||
duration
|
||||
:easing1
|
||||
delay-ms))
|
||||
delay))
|
||||
|
||||
(defn set-value
|
||||
[shared-value value]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns quo2.components.settings.category.settings.view
|
||||
(:require
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.settings.settings-item.view :as settings-item]
|
||||
[quo2.components.settings.settings-list.view :as settings-list]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
@@ -21,7 +21,7 @@
|
||||
[rn/flat-list
|
||||
{:data data
|
||||
:style (style/settings-items theme blur?)
|
||||
:render-fn (fn [item] [settings-item/view item])
|
||||
:render-fn (fn [item] [settings-list/settings-list item])
|
||||
:separator [rn/view {:style (style/settings-separator theme blur?)}]}]])
|
||||
|
||||
(def settings-category (quo.theme/with-theme category-internal))
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
(ns quo2.components.settings.settings-item.component-spec
|
||||
(:require [quo2.components.settings.settings-item.view :as settings-item]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def props
|
||||
{:title "Account"
|
||||
:accessibility-label :settings-item
|
||||
:action :arrow
|
||||
:image :icon
|
||||
:image-props :i/browser})
|
||||
|
||||
(h/describe "Settings list tests"
|
||||
(h/test "Default render of Setting list component"
|
||||
(h/render [settings-item/view props])
|
||||
(h/is-truthy (h/get-by-label-text :settings-item)))
|
||||
|
||||
(h/test "It renders a title"
|
||||
(h/render [settings-item/view props])
|
||||
(h/is-truthy (h/get-by-text "Account")))
|
||||
|
||||
(h/test "its gets passed an on press event"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [settings-item/view
|
||||
(merge props {:on-press event})])
|
||||
(h/fire-event :press (h/get-by-text "Account"))
|
||||
(h/was-called event)))
|
||||
|
||||
(h/test "on change event gets fired for toggle"
|
||||
(let [on-change (h/mock-fn)]
|
||||
(h/render [settings-item/view
|
||||
(merge props
|
||||
{:action :selector
|
||||
:action-props {:on-change on-change}})])
|
||||
(h/fire-event :press (h/get-by-label-text :toggle-off))
|
||||
(h/was-called on-change)))
|
||||
|
||||
(h/test "It renders a label"
|
||||
(h/render [settings-item/view (merge props {:label :color})])
|
||||
(h/is-truthy (h/get-by-label-text :label-component)))
|
||||
|
||||
(h/test "It renders a status tag component"
|
||||
(h/render [settings-item/view
|
||||
(merge props
|
||||
{:tag :context
|
||||
:tag-props {:context "Test Tag"
|
||||
:icon :i/placeholder}})])
|
||||
(h/is-truthy (h/get-by-text "Test Tag")))
|
||||
|
||||
(h/test "on press event gets fired for button"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [settings-item/view
|
||||
(merge props
|
||||
{:action :button
|
||||
:action-props {:button-text "test button"
|
||||
:on-press event}})])
|
||||
(h/fire-event :press (h/get-by-text "test button"))
|
||||
(h/was-called event))))
|
||||
@@ -1,57 +0,0 @@
|
||||
(ns quo2.components.settings.settings-item.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn find-icon-height
|
||||
[description tag image]
|
||||
(let [icon-height (if (= image :icon-avatar) 32 20)
|
||||
icon-height (if description 40 icon-height)]
|
||||
(if tag 72 icon-height)))
|
||||
|
||||
(defn container
|
||||
[{:keys [in-card? tag]}]
|
||||
{:padding-horizontal 12
|
||||
:padding-vertical (if in-card? 12 13)
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:height (if tag 96 48)})
|
||||
|
||||
(def sub-container
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def left-container
|
||||
{:margin-left 12
|
||||
:height "100%"
|
||||
:justify-content :center})
|
||||
|
||||
(defn image-container
|
||||
[description tag image]
|
||||
{:height (find-icon-height description tag image)
|
||||
:justify-content :flex-start})
|
||||
|
||||
(def status-container
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn status-dot
|
||||
[online? theme]
|
||||
{:width 8
|
||||
:height 8
|
||||
:border-radius 8
|
||||
:margin-right 6
|
||||
:background-color (if online?
|
||||
(colors/theme-colors colors/success-50 colors/success-60 theme)
|
||||
(colors/theme-colors colors/danger-50 colors/danger-60 theme))})
|
||||
|
||||
(defn color
|
||||
[blur? theme]
|
||||
{:color (if blur?
|
||||
colors/white-opa-70
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
|
||||
(defn label-dot
|
||||
[background-color]
|
||||
{:width 15
|
||||
:height 15
|
||||
:border-radius 12
|
||||
:background-color background-color})
|
||||
@@ -1,117 +0,0 @@
|
||||
(ns quo2.components.settings.settings-item.view
|
||||
(:require
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.list-items.preview-list.view :as preview-list]
|
||||
[quo2.components.selectors.selectors.view :as selectors]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.avatars.icon-avatar :as icon-avatar]
|
||||
[quo2.components.tags.status-tags :as status-tags]
|
||||
[quo2.components.tags.context-tag.view :as context-tag]
|
||||
[quo2.components.settings.settings-item.style :as style]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn status-description
|
||||
[{:keys [description-props blur? theme]}]
|
||||
(let [{:keys [online? text]} description-props]
|
||||
[rn/view {:style style/status-container}
|
||||
[rn/view {:style (style/status-dot online? blur?)}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/color blur? theme)}
|
||||
(if online? (i18n/label :t/online-now) text)]]))
|
||||
|
||||
(defn text-description
|
||||
[{:keys [description-props blur? theme]}]
|
||||
(let [{:keys [text icon]} description-props]
|
||||
[rn/view
|
||||
{:style style/sub-container}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/color blur? theme)}
|
||||
text]
|
||||
(when icon
|
||||
[icon/icon icon
|
||||
(merge (style/color blur? theme)
|
||||
{:size 16
|
||||
:container-style {:margin-left 4}})])]))
|
||||
|
||||
(defn description-component
|
||||
[{:keys [description] :as props}]
|
||||
(case description
|
||||
:text [text-description props]
|
||||
:text-plus-icon [text-description props]
|
||||
:status [status-description props]
|
||||
nil))
|
||||
|
||||
(defn image-component
|
||||
[{:keys [image image-props description tag blur? theme]}]
|
||||
[rn/view
|
||||
{:style (style/image-container description tag image)}
|
||||
(case image
|
||||
:icon [icon/icon image-props (style/color blur? theme)]
|
||||
:avatar [user-avatar/user-avatar image-props]
|
||||
:icon-avatar [icon-avatar/icon-avatar image-props]
|
||||
nil)])
|
||||
|
||||
(defn tag-component
|
||||
[{:keys [tag tag-props]}]
|
||||
(case tag
|
||||
:positive [status-tags/status-tag
|
||||
{:status {:type :positive}
|
||||
:label (i18n/label :t/positive)
|
||||
:size :small
|
||||
:container-style {:margin-top 8}}]
|
||||
:context [context-tag/view
|
||||
(merge tag-props
|
||||
{:type :icon
|
||||
:size 24
|
||||
:container-style {:margin-top 8
|
||||
:align-self :flex-start}})]
|
||||
nil))
|
||||
|
||||
(defn label-component
|
||||
[{:keys [label label-props blur? theme]}]
|
||||
[rn/view {:accessibility-label :label-component}
|
||||
(case label
|
||||
:text [text/text
|
||||
{:style (style/color blur? theme)}
|
||||
label-props]
|
||||
:color [rn/view
|
||||
{:style (style/label-dot label-props)}]
|
||||
:preview [preview-list/view {:type (:type label-props)} (:data label-props)]
|
||||
nil)])
|
||||
|
||||
(defn action-component
|
||||
[{:keys [action action-props blur? theme]}]
|
||||
[rn/view {:style {:margin-left 12}}
|
||||
(case action
|
||||
:arrow [icon/icon :i/chevron-right (style/color blur? theme)]
|
||||
:button [button/button
|
||||
{:type :outline
|
||||
:size 24
|
||||
:on-press (:on-press action-props)}
|
||||
(:button-text action-props)]
|
||||
:selector [selectors/toggle action-props]
|
||||
nil)])
|
||||
|
||||
(defn- internal-view
|
||||
[{:keys [title on-press accessibility-label] :as props}]
|
||||
[rn/pressable
|
||||
{:style (style/container props)
|
||||
:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view {:style style/sub-container}
|
||||
[image-component props]
|
||||
[rn/view {:style style/left-container}
|
||||
[text/text {:weight :medium} title]
|
||||
[description-component props]
|
||||
[tag-component props]]]
|
||||
[rn/view {:style style/sub-container}
|
||||
[label-component props]
|
||||
[action-component props]]])
|
||||
|
||||
(def view (quo.theme/with-theme internal-view))
|
||||
@@ -0,0 +1,58 @@
|
||||
(ns quo2.components.settings.settings-list.component-spec
|
||||
(:require [quo2.components.settings.settings-list.view :as settings-list]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Settings list tests"
|
||||
(h/test "Default render of Setting list component"
|
||||
(h/render [settings-list/settings-list {:accessibility-label "test"}])
|
||||
(h/is-truthy (h/get-by-label-text :test)))
|
||||
|
||||
(h/test "It renders a title"
|
||||
(h/render [settings-list/settings-list {:title "test"}])
|
||||
(h/is-truthy (h/get-by-text "test")))
|
||||
|
||||
(h/test "its gets passed an on press event"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [settings-list/settings-list
|
||||
{:title "test"
|
||||
:on-press event}])
|
||||
(h/fire-event :press (h/get-by-text "test"))
|
||||
(h/was-called event)))
|
||||
|
||||
(h/test "on change event gets fired for toggle"
|
||||
(let [on-change (h/mock-fn)]
|
||||
(h/render [settings-list/settings-list
|
||||
{:title "test"
|
||||
:toggle-props {:on-change on-change}}])
|
||||
(h/fire-event :press (h/get-by-label-text :toggle-off))
|
||||
(h/was-called on-change)))
|
||||
|
||||
(h/test "It renders a badge"
|
||||
(h/render [settings-list/settings-list {:badge? true}])
|
||||
(h/is-truthy (h/get-by-label-text :setting-list-badge)))
|
||||
|
||||
(h/test "It renders a status tag component"
|
||||
(h/render [settings-list/settings-list
|
||||
{:status-tag-props
|
||||
{:size :small
|
||||
:status {:type :positive}
|
||||
:label "test tag"}}])
|
||||
(h/is-truthy (h/get-by-text "test tag")))
|
||||
|
||||
(h/test "on press event gets fired for button"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [settings-list/settings-list
|
||||
{:button-props {:title "test button"
|
||||
:on-press event}}])
|
||||
(h/fire-event :press (h/get-by-text "test button"))
|
||||
(h/was-called event)))
|
||||
|
||||
(h/test "It renders a list of community icons"
|
||||
(h/render [settings-list/settings-list
|
||||
{:communities-props {:data
|
||||
[{:source "1"
|
||||
:accessibility-label :community-1}
|
||||
{:source "2"
|
||||
:accessibility-label :community-2}]}}])
|
||||
(h/is-truthy (h/get-by-label-text :community-1))
|
||||
(h/is-truthy (h/get-by-label-text :community-2))))
|
||||
@@ -52,5 +52,4 @@
|
||||
:margin-right 12})
|
||||
|
||||
(def tag-container
|
||||
{:margin-top 8
|
||||
:margin-left -1})
|
||||
{:margin-top 8})
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
(ns quo2.components.settings.settings-list.view
|
||||
(:require [quo2.components.settings.settings-list.style :as style]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.selectors.selectors.view :as selectors]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.tags.status-tags :as status-tag]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn settings-title
|
||||
[title status-tag-props override-theme]
|
||||
[rn/view
|
||||
{:style style/title-container}
|
||||
(when title
|
||||
[text/text
|
||||
{:accessibility-label :setting-item-name-text
|
||||
:ellipsize-mode :tail
|
||||
:style (style/title override-theme)
|
||||
:override-theme override-theme
|
||||
:number-of-lines 1
|
||||
:weight :medium
|
||||
:size :paragraph-1}
|
||||
title])
|
||||
(when status-tag-props
|
||||
[rn/view {:style style/tag-container}
|
||||
[status-tag/status-tag
|
||||
status-tag-props]])])
|
||||
|
||||
(defn left-icon-comp
|
||||
[icon]
|
||||
[rn/view {:style style/icon}
|
||||
[icons/icon icon
|
||||
{:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)}]])
|
||||
|
||||
(def chevron-icon
|
||||
[rn/view
|
||||
[icons/icon :chevron-right
|
||||
{:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)}]])
|
||||
|
||||
(defn toggle-button
|
||||
[{:keys [checked?
|
||||
on-change]}]
|
||||
[selectors/toggle
|
||||
{:checked? checked?
|
||||
:on-change (fn [new-value] (on-change new-value))}])
|
||||
|
||||
(defn badge-icon
|
||||
[override-theme]
|
||||
[rn/view
|
||||
{:accessible :true
|
||||
:accessibility-label :setting-list-badge
|
||||
:style (style/dot override-theme)}])
|
||||
|
||||
(defn right-button
|
||||
[{:keys [title
|
||||
on-press]}]
|
||||
[button/button
|
||||
{:type :outline
|
||||
:on-press on-press
|
||||
:size 24}
|
||||
title])
|
||||
|
||||
(defn communities-icons
|
||||
[{:keys [data
|
||||
icon-style]}
|
||||
override-theme]
|
||||
(let [communities-count (dec (count data))]
|
||||
[rn/view
|
||||
{:style style/communities-container}
|
||||
(map-indexed
|
||||
(fn [index {:keys [source accessibility-label]}]
|
||||
[rn/image
|
||||
{:key source
|
||||
:source (if (string? source)
|
||||
{:uri source}
|
||||
source)
|
||||
:accessibility-label accessibility-label
|
||||
:style (merge (style/community-icon (- communities-count index) override-theme)
|
||||
icon-style)}])
|
||||
data)]))
|
||||
|
||||
(defn settings-list
|
||||
"Options
|
||||
- `title` String to show in the center of the component, right to the icon and left to optional gadgets.
|
||||
- `on-press` Callback called when the component is pressed.
|
||||
- `accessibility-label` String to use as accessibility-label for VoiceOver.
|
||||
- `left-icon` icon keyword for icon on left.
|
||||
- `chevron?` Boolean to show/hide chevron at the right border of the component.
|
||||
- `toggle-prop` Map with the following keys:
|
||||
`checked?` Boolean value to set check or unchecked toggle.
|
||||
`on-change` Callback called when user toggles toggle. Will pass the new toggle value to the callback
|
||||
- `badge?` Boolean to show/hide badge.
|
||||
- `button-props` Map with the following keys:
|
||||
`title` String to show as button text.
|
||||
`on-press` Callback called when button is pressed.
|
||||
- `communities-props` Map with the following keys:
|
||||
`data` Array of maps containg source of the community asset.
|
||||
- `style` Styles map to be merge with default container styles.
|
||||
- `overide-theme` :dark or :light
|
||||
- `status-tag-props see the spec for status-tag component
|
||||
"
|
||||
|
||||
[{:keys [title
|
||||
on-press
|
||||
accessibility-label
|
||||
left-icon
|
||||
chevron?
|
||||
toggle-props
|
||||
badge?
|
||||
button-props
|
||||
communities-props
|
||||
container-style
|
||||
override-theme
|
||||
status-tag-props]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view
|
||||
{:style (merge style/item-container container-style)}
|
||||
[rn/view {:style style/inner-container}
|
||||
(when left-icon
|
||||
[left-icon-comp left-icon])
|
||||
[settings-title title status-tag-props override-theme]
|
||||
(when toggle-props
|
||||
[toggle-button toggle-props])
|
||||
(when badge? [badge-icon override-theme])
|
||||
(when button-props
|
||||
[right-button button-props])
|
||||
(when communities-props (communities-icons communities-props override-theme))
|
||||
(when chevron? chevron-icon)]]])
|
||||
@@ -28,6 +28,10 @@
|
||||
:background-color background-color
|
||||
:border-radius 12})
|
||||
|
||||
(def account-emoji
|
||||
{:height 16
|
||||
:width 16})
|
||||
|
||||
(def account-avatar-container
|
||||
{:margin-left 4
|
||||
:margin-right 8})
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.common.notification-dot.view :as notification-dot]
|
||||
[quo2.components.tabs.tab.style :as style]
|
||||
[quo2.theme :as quo.theme]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.svg :as svg]))
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
(vector? children)
|
||||
children)])
|
||||
|
||||
(defn- view-internal
|
||||
(defn- themed-view
|
||||
[{:keys [accessibility-label
|
||||
active
|
||||
before
|
||||
@@ -104,4 +104,4 @@
|
||||
:disabled disabled
|
||||
:background-color background-color}])]]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view (theme/with-theme themed-view))
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
;; Truncate to avoid unnecessary rendering.
|
||||
(if (> fade-percentage 0.99)
|
||||
0.99
|
||||
max-fade-percentage)))
|
||||
(utils.number/naive-round fade-percentage 2))))
|
||||
|
||||
(defn- masked-view-wrapper
|
||||
[{:keys [fade-end-percentage fade-end?]} & children]
|
||||
@@ -59,10 +59,8 @@
|
||||
(when on-scroll
|
||||
(on-scroll e)))
|
||||
|
||||
(defn- tab-view
|
||||
[{:keys [id label notification-dot? accessibility-label]}
|
||||
index _
|
||||
{:keys [active-tab-id
|
||||
(defn- render-tab
|
||||
[{:keys [active-tab-id
|
||||
blur?
|
||||
customization-color
|
||||
flat-list-ref
|
||||
@@ -70,8 +68,9 @@
|
||||
on-change
|
||||
scroll-on-press?
|
||||
size
|
||||
style
|
||||
]}]
|
||||
style]}
|
||||
{:keys [id label notification-dot? accessibility-label]}
|
||||
index]
|
||||
[rn/view
|
||||
{:style (style/tab {:size size
|
||||
:default-tab-size default-tab-size
|
||||
@@ -167,6 +166,7 @@
|
||||
;; just one about this topic:
|
||||
;; https://github.com/facebook/react-native/issues/31218
|
||||
:content-container-style {:padding-top (dec unread-count-offset)}
|
||||
:extra-data (str @active-tab-id)
|
||||
:horizontal true
|
||||
:scroll-event-throttle 64
|
||||
:shows-horizontal-scroll-indicator false
|
||||
@@ -178,20 +178,20 @@
|
||||
:fade-end? fade-end?
|
||||
:fading fading
|
||||
:on-scroll on-scroll})
|
||||
:render-fn tab-view
|
||||
:render-data {:active-tab-id active-tab-id
|
||||
:blur? blur?
|
||||
:customization-color customization-color
|
||||
:flat-list-ref flat-list-ref
|
||||
:number-of-items (count data)
|
||||
:on-change on-change
|
||||
:scroll-on-press? scroll-on-press?
|
||||
:size size
|
||||
:style style}})]]]
|
||||
:render-fn (partial render-tab
|
||||
{:active-tab-id active-tab-id
|
||||
:blur? blur?
|
||||
:customization-color customization-color
|
||||
:flat-list-ref flat-list-ref
|
||||
:number-of-items (count data)
|
||||
:on-change on-change
|
||||
:scroll-on-press? scroll-on-press?
|
||||
:size size
|
||||
:style style})})]]]
|
||||
[rn/view (merge style {:flex-direction :row})
|
||||
(map-indexed (fn [index item]
|
||||
^{:key (:id item)}
|
||||
[tab-view item index nil
|
||||
[render-tab
|
||||
{:active-tab-id active-tab-id
|
||||
:blur? blur?
|
||||
:customization-color customization-color
|
||||
@@ -199,5 +199,6 @@
|
||||
:on-change on-change
|
||||
:size size
|
||||
:style style}
|
||||
])
|
||||
item
|
||||
index])
|
||||
data)]))))
|
||||
|
||||
@@ -73,19 +73,18 @@
|
||||
(defn- view-internal
|
||||
[{:keys [theme type size state blur? customization-color profile-picture full-name users
|
||||
group-name token-logo amount token-name network-logo network-name networks
|
||||
account-name emoji collectible collectible-name collectible-number duration container-style]
|
||||
account-name emoji collectible collectible-name collectible-number duration]
|
||||
:or {customization-color :blue
|
||||
type :default
|
||||
state :default}
|
||||
:as props}]
|
||||
[rn/view
|
||||
{:style (merge (style/container {:theme theme
|
||||
:type type
|
||||
:size size
|
||||
:state state
|
||||
:blur? blur?
|
||||
:customization-color customization-color})
|
||||
container-style)}
|
||||
{:style (style/container {:theme theme
|
||||
:type type
|
||||
:size size
|
||||
:state state
|
||||
:blur? blur?
|
||||
:customization-color customization-color})}
|
||||
(case type
|
||||
:default
|
||||
[tag-skeleton {:theme theme :size size :text full-name}
|
||||
@@ -93,8 +92,7 @@
|
||||
{:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:size (if (= size 24) :xxs 28)
|
||||
:status-indicator? false
|
||||
:ring? false}]]
|
||||
:status-indicator? false}]]
|
||||
|
||||
:multiuser
|
||||
[preview-list/view {:type :user :size 20}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
(ns quo2.components.tags.network-tags.component-spec
|
||||
(:require [quo2.components.tags.network-tags.view :as network-tags]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "network-tags component"
|
||||
(h/test "renders network tags with single network"
|
||||
(h/render [network-tags/view
|
||||
{:title "Network Tags"
|
||||
:networks [{:source "network-icon.png"}]}])
|
||||
(h/is-truthy (h/get-by-text "Network Tags")))
|
||||
|
||||
(h/test "renders network tags with multiple networks"
|
||||
(h/render [network-tags/view
|
||||
{:title "Multiple Networks"
|
||||
:networks [{:source "network-icon1.png"}
|
||||
{:source "network-icon2.png"}
|
||||
{:source "network-icon3.png"}]
|
||||
:size :size/s-32}])
|
||||
(h/is-truthy (h/get-by-text "Multiple Networks"))))
|
||||
@@ -1,41 +0,0 @@
|
||||
(ns quo2.components.tags.network-tags.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
[{:keys [status theme blur?]}]
|
||||
{:flex-direction :row
|
||||
:align-self :flex-start
|
||||
:background-color (when (= status :error)
|
||||
(colors/theme-colors
|
||||
(colors/custom-color :danger 50 10)
|
||||
(colors/custom-color :danger 60 10)
|
||||
theme))
|
||||
:border-width 1
|
||||
:border-color (cond (= status :error)
|
||||
(colors/theme-colors
|
||||
(colors/custom-color :danger 50 20)
|
||||
(colors/custom-color :danger 60 20)
|
||||
theme)
|
||||
(and blur? (= status :default)) (colors/theme-colors
|
||||
colors/neutral-80-opa-5
|
||||
colors/white-opa-5
|
||||
theme)
|
||||
:else (colors/theme-colors
|
||||
colors/neutral-20
|
||||
colors/neutral-80
|
||||
theme))
|
||||
:border-radius 8
|
||||
:padding-left 5
|
||||
:padding-right 5
|
||||
:padding-top 3
|
||||
:padding-bottom 2})
|
||||
|
||||
(defn title-style
|
||||
[{:keys [status theme]}]
|
||||
{:padding-left 4
|
||||
:margin-top -1
|
||||
:color (when (= status :error)
|
||||
(colors/theme-colors
|
||||
(colors/custom-color :danger 50)
|
||||
(colors/custom-color :danger 60)
|
||||
theme))})
|
||||
@@ -1,25 +0,0 @@
|
||||
(ns quo2.components.tags.network-tags.view
|
||||
(:require [quo2.components.list-items.preview-list.view :as preview-list]
|
||||
[quo2.components.tags.network-tags.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as quo.theme]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [title networks status theme blur?] :or {status :default}}]
|
||||
[rn/view
|
||||
{:style (style/container {:status status
|
||||
:theme theme
|
||||
:blur? blur?})}
|
||||
[preview-list/view
|
||||
{:type :network
|
||||
:number (count networks)
|
||||
:size :size/s-16} networks]
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style (style/title-style {:status status
|
||||
:theme theme})}
|
||||
title]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -1,20 +0,0 @@
|
||||
(ns quo2.components.tags.number-tag.component-spec
|
||||
(:require [quo2.components.tags.number-tag.view :as number-tag]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe
|
||||
"number tag component test"
|
||||
(h/test "+3 render"
|
||||
(h/render [number-tag/view
|
||||
{:type :rounded
|
||||
:number "3"
|
||||
:size :size/s-32
|
||||
:blur? false}])
|
||||
(h/is-truthy (h/get-by-text "+3")))
|
||||
(h/test "+48 render"
|
||||
(h/render [number-tag/view
|
||||
{:type :squared
|
||||
:number "48"
|
||||
:size :size/s-24
|
||||
:blur? true}])
|
||||
(h/is-truthy (h/get-by-text "+48"))))
|
||||