rebasing fdroid branch
11
README.md
@ -34,13 +34,10 @@ Databag is designed for efficiency, consuming minimal hosting resources. Notable
|
||||
- Lightweight (server can run on a raspberry pi zero v1.3)
|
||||
- Low latency (use of websockets for push events to avoid polling)
|
||||
- Unlimited accounts per node (host for your whole family)
|
||||
- Mobile alerts for new contacts, messages, and calls (supports UnifiedPush, FCM, APN)
|
||||
- Mobile alerts (push notifications on new contacts, messages, and calls)
|
||||
|
||||
<br>
|
||||
<p align="center">
|
||||
<a href="https://f-droid.org/en/packages/com.databag/">
|
||||
<img src="/doc/fdroid.png" width="18%">
|
||||
</a>
|
||||
<a href="https://apps.apple.com/us/app/databag/id6443741428">
|
||||
<img src="/doc/astore.png" width="18%">
|
||||
</a>
|
||||
@ -49,7 +46,7 @@ Databag is designed for efficiency, consuming minimal hosting resources. Notable
|
||||
</a>
|
||||
</p>
|
||||
|
||||
The app is available on fdroid as well as the google and apple stores. You can test out the project [here](https://databag.coredb.org/#/create), but don't post anything important as this server is regularly wiped. Feedback on the UI/UX, bugs or features is greatly appreciated.
|
||||
The app is available in the google and apple stores. You can also test out the project [here](https://databag.coredb.org/#/create), but don't post anything important as this server is regularly wiped. Feedback on the UI/UX, bugs or features is greatly appreciated.
|
||||
|
||||
## Installation
|
||||
|
||||
@ -63,7 +60,7 @@ From the net/container sub directory:
|
||||
### Example with Portainer and Nginx Proxy Manager
|
||||
|
||||
From Portainer:
|
||||
- In the volume view, click add volume:
|
||||
- In the volume view, click add volumen:
|
||||
- Enter a name, then click 'Create the volume'
|
||||
- In the container view, click add container:
|
||||
- In the 'Image' field enter 'balzack/databag:latest'
|
||||
@ -143,7 +140,7 @@ Integrate Databag in an OpenWrt firmware [here](/doc/openwrt.md).
|
||||
|
||||
## Audio and Video Calls
|
||||
|
||||
Databag provides audio and video calling and relies on a STUN/TURN relay server for NAT traversal. Testing was done with both [coturn](https://github.com/coturn/coturn) and [pion](https://github.com/pion/turn) and should work with any implementation. Instructions for installing a coturn server are provided [here](https://gabrieltanner.org/blog/turn-server/).
|
||||
Databag provides audio and video calling and relies on a STUN/TURN relay server for NAT traversal. Testing was done with both [cuturn](https://github.com/coturn/coturn) and [pion](https://github.com/pion/turn) and should work with any implementation. Instructions for installing a coturn server are provided [here](https://gabrieltanner.org/blog/turn-server/).
|
||||
|
||||
If you want to enable audio and video calls, you should setup your own relay server. For testing purposes you can however use the demo relay server configuration. In the admin configuration modal, set:
|
||||
- Enable WebRTC Calls: -switch on-
|
||||
|
@ -20,7 +20,7 @@ import { Dashboard } from 'src/dashboard/Dashboard';
|
||||
import { Session } from 'src/session/Session';
|
||||
import { Prompt } from 'utils/Prompt';
|
||||
import ReceiveSharingIntent from 'react-native-receive-sharing-intent';
|
||||
import { Platform, PermissionsAndroid } from 'react-native';
|
||||
import {PermissionsAndroid} from 'react-native';
|
||||
import { initUnifiedPush } from 'react-native-unifiedpush-connector';
|
||||
import { MenuProvider } from 'react-native-popup-menu';
|
||||
|
||||
@ -32,11 +32,8 @@ export default function App() {
|
||||
const [sharing, setSharing] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (Platform.OS !== 'ios') {
|
||||
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
||||
initUnifiedPush();
|
||||
}
|
||||
|
||||
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
||||
|
||||
ReceiveSharingIntent.getReceivedFiles(files => {
|
||||
setSharing(files);
|
||||
|
@ -1,5 +1,4 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
import com.android.build.OutputFile
|
||||
@ -59,7 +58,7 @@ react {
|
||||
* use App Bundles (https://developer.android.com/guide/app-bundle/)
|
||||
* and want to have separate APKs to upload to the Play Store.
|
||||
*/
|
||||
def enableSeparateBuildPerCPUArchitecture = false
|
||||
def enableSeparateBuildPerCPUArchitecture = true
|
||||
|
||||
/**
|
||||
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
|
||||
@ -94,18 +93,18 @@ android {
|
||||
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
namespace "com.databag"
|
||||
defaultConfig {
|
||||
applicationId "com.databag"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1018
|
||||
versionName "1.5"
|
||||
versionCode 13
|
||||
versionName "1.1"
|
||||
}
|
||||
|
||||
splits {
|
||||
@ -116,6 +115,7 @@ compileOptions {
|
||||
include (*reactNativeArchitectures())
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file('balzack.keystore')
|
||||
@ -124,6 +124,7 @@ compileOptions {
|
||||
keyPassword 'balzack'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
@ -158,7 +159,6 @@ dependencies {
|
||||
// The version of react-native is set by the React Native Gradle Plugin
|
||||
implementation("com.facebook.react:react-android")
|
||||
|
||||
|
||||
implementation 'androidx.core:core:1.8.0'
|
||||
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
|
||||
|
@ -1,39 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "627079362503",
|
||||
"project_id": "databag-b46e0",
|
||||
"storage_bucket": "databag-b46e0.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:627079362503:android:6f3dfcb2c255787b4a8be2",
|
||||
"android_client_info": {
|
||||
"package_name": "com.databag"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "627079362503-8bk8o4hcv5rgdgrhik6nu9cjp3poisv7.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAb92cvtSnaoQzhbDizg0dFskOtZFp_58M"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "627079362503-8bk8o4hcv5rgdgrhik6nu9cjp3poisv7.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
@ -17,9 +17,10 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission tools:node="remove" android:name="android.vending.CHECK_LICENSE" />
|
||||
<uses-permission tools:node="remove" android:name="com.android.vending.CHECK_LICENSE" />
|
||||
|
||||
<application
|
||||
android:usesCleartextTraffic="true"
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@ -78,7 +79,7 @@
|
||||
|
||||
<receiver
|
||||
android:enabled="true"
|
||||
android:name="com.unifiedpushconnector.CustomReceiver"
|
||||
android:name=".CustomReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
|
||||
|
@ -0,0 +1,103 @@
|
||||
package com.databag;
|
||||
|
||||
import android.content.Context;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.unifiedpush.android.connector.MessagingReceiver;
|
||||
import android.util.Log;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.app.ActivityManager.RunningAppProcessInfo;
|
||||
import android.app.ActivityManager;
|
||||
import android.os.Build;
|
||||
import android.net.Uri;
|
||||
import android.media.RingtoneManager;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
|
||||
public class CustomReceiver extends MessagingReceiver {
|
||||
public CustomReceiver() {
|
||||
super();
|
||||
}
|
||||
|
||||
private boolean forgrounded () {
|
||||
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
|
||||
ActivityManager.getMyMemoryState(appProcessInfo);
|
||||
return (appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND || appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewEndpoint(@NotNull Context context, @NotNull String endpoint, @NotNull String instance) {
|
||||
|
||||
final ReactInstanceManager reactInstanceManager =
|
||||
((ReactApplication) context.getApplicationContext())
|
||||
.getReactNativeHost()
|
||||
.getReactInstanceManager();
|
||||
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
|
||||
|
||||
WritableMap params = Arguments.createMap();
|
||||
params.putString("instance", instance);
|
||||
params.putString("endpoint", endpoint);
|
||||
reactContext
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit("unifiedPushURL", params);
|
||||
|
||||
// Called when a new endpoint be used for sending push messages
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegistrationFailed(@NotNull Context context, @NotNull String instance) {
|
||||
// called when the registration is not possible, eg. no network
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnregistered(@NotNull Context context, @NotNull String instance) {
|
||||
// called when this application is unregistered from receiving push messages
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(@NotNull Context context, @NotNull byte[] message, @NotNull String instance) {
|
||||
|
||||
if (forgrounded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String strMessage = new String(message, StandardCharsets.UTF_8);
|
||||
|
||||
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* Request code */, intent,
|
||||
PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
String channelId = "fcm_default_channel";
|
||||
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context,
|
||||
channelId)
|
||||
.setSmallIcon(R.mipmap.ic_launcher)
|
||||
.setContentTitle(strMessage).setAutoCancel(true).setSound(
|
||||
defaultSoundUri).setContentIntent(pendingIntent);
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
|
||||
Context.NOTIFICATION_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(channelId, "Channel human readable title",
|
||||
NotificationManager.IMPORTANCE_DEFAULT);
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
notificationManager.notify(0, notificationBuilder.build());
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,25 @@ public class MainActivity extends ReactActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(null);
|
||||
MainActivity activityContext = this;
|
||||
|
||||
this.getSharedPreferences("unifiedpush.connector", Context.MODE_PRIVATE).edit().putBoolean("unifiedpush.no_distrib_dialog", true).apply();
|
||||
|
||||
|
||||
ReactInstanceManager mReactInstanceManager = getReactNativeHost().getReactInstanceManager();
|
||||
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
|
||||
public void onReactContextInitialized(ReactContext validContext) {
|
||||
|
||||
UnifiedPush.registerAppWithDialog(
|
||||
activityContext,
|
||||
"default",
|
||||
new RegistrationDialogContent(),
|
||||
new ArrayList<String>(),
|
||||
getApplicationContext().getPackageName()
|
||||
);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,6 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.gms:google-services:4.3.15'
|
||||
classpath("com.android.tools.build:gradle:7.3.1")
|
||||
classpath("com.facebook.react:react-native-gradle-plugin")
|
||||
}
|
||||
@ -32,3 +31,4 @@ allprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,10 +7,5 @@ import 'react-native-gesture-handler';
|
||||
import {AppRegistry} from 'react-native';
|
||||
import App from './App';
|
||||
import {name as appName} from './app.json';
|
||||
import messaging from '@react-native-firebase/messaging';
|
||||
|
||||
messaging().registerDeviceForRemoteMessages().then(() => {});
|
||||
|
||||
messaging().setBackgroundMessageHandler(async remoteMessage => {});
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App);
|
||||
|
@ -9,64 +9,8 @@ PODS:
|
||||
- React-Core (= 0.71.3)
|
||||
- React-jsi (= 0.71.3)
|
||||
- ReactCommon/turbomodule/core (= 0.71.3)
|
||||
- Firebase/CoreOnly (10.7.0):
|
||||
- FirebaseCore (= 10.7.0)
|
||||
- Firebase/Messaging (10.7.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 10.7.0)
|
||||
- FirebaseCore (10.7.0):
|
||||
- FirebaseCoreInternal (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Logger (~> 7.8)
|
||||
- FirebaseCoreExtension (10.7.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseCoreInternal (10.22.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- FirebaseInstallations (10.22.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebaseMessaging (10.7.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleDataTransport (~> 9.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Reachability (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- fmt (6.2.1)
|
||||
- glog (0.3.5)
|
||||
- GoogleDataTransport (9.4.1):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.13.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Environment (7.13.0):
|
||||
- GoogleUtilities/Privacy
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.13.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Network (7.13.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.13.0)":
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (7.13.0)
|
||||
- GoogleUtilities/Reachability (7.13.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/UserDefaults (7.13.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- hermes-engine (0.71.3):
|
||||
- hermes-engine/Pre-built (= 0.71.3)
|
||||
- hermes-engine/Pre-built (0.71.3)
|
||||
@ -81,15 +25,7 @@ PODS:
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.3.2):
|
||||
- libwebp/demux
|
||||
- libwebp/sharpyuv (1.3.2)
|
||||
- libwebp/webp (1.3.2):
|
||||
- libwebp/sharpyuv
|
||||
- nanopb (2.30909.1):
|
||||
- nanopb/decode (= 2.30909.1)
|
||||
- nanopb/encode (= 2.30909.1)
|
||||
- nanopb/decode (2.30909.1)
|
||||
- nanopb/encode (2.30909.1)
|
||||
- PromisesObjC (2.4.0)
|
||||
- libwebp/webp (1.2.4)
|
||||
- RCT-Folly (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
@ -341,21 +277,19 @@ PODS:
|
||||
- React-jsinspector (0.71.3)
|
||||
- React-logger (0.71.3):
|
||||
- glog
|
||||
- react-native-blur (4.3.2):
|
||||
- React-Core
|
||||
- react-native-create-thumbnail (1.6.4):
|
||||
- React-Core
|
||||
- react-native-document-picker (8.2.1):
|
||||
- react-native-document-picker (8.1.3):
|
||||
- React-Core
|
||||
- react-native-image-resizer (3.0.5):
|
||||
- React-Core
|
||||
- react-native-keep-awake (1.2.0):
|
||||
- react-native-keep-awake (1.1.0):
|
||||
- React-Core
|
||||
- react-native-receive-sharing-intent (2.0.0):
|
||||
- React-Core
|
||||
- react-native-rsa-native (2.0.5):
|
||||
- React
|
||||
- react-native-safe-area-context (4.6.3):
|
||||
- react-native-safe-area-context (4.5.0):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
@ -363,8 +297,6 @@ PODS:
|
||||
- ReactCommon/turbomodule/core
|
||||
- react-native-sqlite-storage (6.0.1):
|
||||
- React-Core
|
||||
- react-native-unifiedpush-connector (0.1.8):
|
||||
- React-Core
|
||||
- react-native-video (5.2.1):
|
||||
- React-Core
|
||||
- react-native-video/Video (= 5.2.1)
|
||||
@ -461,25 +393,17 @@ PODS:
|
||||
- React-Core
|
||||
- rn-fetch-blob (0.12.0):
|
||||
- React-Core
|
||||
- RNCClipboard (1.11.2):
|
||||
- RNCClipboard (1.11.1):
|
||||
- React-Core
|
||||
- RNDeviceInfo (10.6.1):
|
||||
- RNDeviceInfo (10.4.0):
|
||||
- React-Core
|
||||
- RNFastImage (8.6.3):
|
||||
- React-Core
|
||||
- SDWebImage (~> 5.11.1)
|
||||
- SDWebImageWebPCoder (~> 0.8.4)
|
||||
- RNFBApp (17.5.0):
|
||||
- Firebase/CoreOnly (= 10.7.0)
|
||||
- React-Core
|
||||
- RNFBMessaging (17.5.0):
|
||||
- Firebase/Messaging (= 10.7.0)
|
||||
- FirebaseCoreExtension (= 10.7.0)
|
||||
- React-Core
|
||||
- RNFBApp
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.12.0):
|
||||
- RNGestureHandler (2.9.0):
|
||||
- React-Core
|
||||
- RNImageCropPicker (0.39.0):
|
||||
- React-Core
|
||||
@ -490,7 +414,7 @@ PODS:
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- TOCropViewController
|
||||
- RNReanimated (2.17.0):
|
||||
- RNReanimated (2.14.4):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
@ -517,7 +441,7 @@ PODS:
|
||||
- React-RCTText
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNScreens (3.22.0):
|
||||
- RNScreens (3.20.0):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNShare (8.2.2):
|
||||
@ -556,7 +480,6 @@ DEPENDENCIES:
|
||||
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
|
||||
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
|
||||
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
|
||||
- react-native-create-thumbnail (from `../node_modules/react-native-create-thumbnail`)
|
||||
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
||||
- "react-native-image-resizer (from `../node_modules/@bam.tech/react-native-image-resizer`)"
|
||||
@ -565,7 +488,6 @@ DEPENDENCIES:
|
||||
- react-native-rsa-native (from `../node_modules/react-native-rsa-native`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- react-native-sqlite-storage (from `../node_modules/react-native-sqlite-storage`)
|
||||
- react-native-unifiedpush-connector (from `../node_modules/react-native-unifiedpush-connector`)
|
||||
- react-native-video (from `../node_modules/react-native-video`)
|
||||
- react-native-webrtc (from `../node_modules/react-native-webrtc`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
@ -586,8 +508,6 @@ DEPENDENCIES:
|
||||
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNFastImage (from `../node_modules/react-native-fast-image`)
|
||||
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
|
||||
- "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)"
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
@ -599,20 +519,10 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Firebase
|
||||
- FirebaseCore
|
||||
- FirebaseCoreExtension
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- fmt
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- JitsiWebRTC
|
||||
- libevent
|
||||
- libwebp
|
||||
- nanopb
|
||||
- PromisesObjC
|
||||
- SDWebImage
|
||||
- SDWebImageWebPCoder
|
||||
- TOCropViewController
|
||||
@ -658,8 +568,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon/jsinspector"
|
||||
React-logger:
|
||||
:path: "../node_modules/react-native/ReactCommon/logger"
|
||||
react-native-blur:
|
||||
:path: "../node_modules/@react-native-community/blur"
|
||||
react-native-create-thumbnail:
|
||||
:path: "../node_modules/react-native-create-thumbnail"
|
||||
react-native-document-picker:
|
||||
@ -676,8 +584,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-sqlite-storage:
|
||||
:path: "../node_modules/react-native-sqlite-storage"
|
||||
react-native-unifiedpush-connector:
|
||||
:path: "../node_modules/react-native-unifiedpush-connector"
|
||||
react-native-video:
|
||||
:path: "../node_modules/react-native-video"
|
||||
react-native-webrtc:
|
||||
@ -718,10 +624,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-device-info"
|
||||
RNFastImage:
|
||||
:path: "../node_modules/react-native-fast-image"
|
||||
RNFBApp:
|
||||
:path: "../node_modules/@react-native-firebase/app"
|
||||
RNFBMessaging:
|
||||
:path: "../node_modules/@react-native-firebase/messaging"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
@ -744,22 +646,12 @@ SPEC CHECKSUMS:
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: 60195509584153283780abdac5569feffb8f08cc
|
||||
FBReactNativeSpec: 9c191fb58d06dc05ab5559a5505fc32139e9e4a2
|
||||
Firebase: 0219acf760880eeec8ce479895bd7767466d9f81
|
||||
FirebaseCore: e317665b9d744727a97e623edbbed009320afdd7
|
||||
FirebaseCoreExtension: f17247ba8c61e4d3c8d136b5e2de3cb4ac6a85b6
|
||||
FirebaseCoreInternal: bca337352024b18424a61e478460547d46c4c753
|
||||
FirebaseInstallations: 763814908793c0da14c18b3dcffdec71e29ed55e
|
||||
FirebaseMessaging: ac9062bcc35ed56e15a0241d8fd317022499baf8
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
||||
GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152
|
||||
hermes-engine: 38bfe887e456b33b697187570a08de33969f5db7
|
||||
JitsiWebRTC: 3a41671ef65a51d7204323814b055a2690b921c7
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
|
||||
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
||||
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
||||
RCTRequired: bec48f07daf7bcdc2655a0cde84e07d24d2a9e2a
|
||||
RCTTypeSafety: 171394eebacf71e1cfad79dbfae7ee8fc16ca80a
|
||||
@ -774,16 +666,14 @@ SPEC CHECKSUMS:
|
||||
React-jsiexecutor: 515b703d23ffadeac7687bc2d12fb08b90f0aaa1
|
||||
React-jsinspector: 9f7c9137605e72ca0343db4cea88006cb94856dd
|
||||
React-logger: 957e5dc96d9dbffc6e0f15e0ee4d2b42829ff207
|
||||
react-native-blur: cfdad7b3c01d725ab62a8a729f42ea463998afa2
|
||||
react-native-create-thumbnail: e022bcdcba8a0b4529a50d3fa1a832ec921be39d
|
||||
react-native-document-picker: 69ca2094d8780cfc1e7e613894d15290fdc54bba
|
||||
react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c
|
||||
react-native-image-resizer: 00ceb0e05586c7aadf061eea676957a6c2ec60fa
|
||||
react-native-keep-awake: caee3ff89eaa21dfe29010f0d143566874a04441
|
||||
react-native-keep-awake: acbee258db16483744910f0da3ace39eb9ab47fd
|
||||
react-native-receive-sharing-intent: 62ab28c50e6ae56d32b9e841d7452091312a0bc7
|
||||
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
|
||||
react-native-safe-area-context: 36cc67648134e89465663b8172336a19eeda493d
|
||||
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
||||
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261
|
||||
react-native-unifiedpush-connector: 4d60170e5eb46329f15e5da6c1171d3683480bf4
|
||||
react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253
|
||||
react-native-webrtc: a0a8a1730b6cc5a5bda8a6e2166a74c9b78029e2
|
||||
React-perflogger: af8a3d31546077f42d729b949925cc4549f14def
|
||||
@ -801,16 +691,14 @@ SPEC CHECKSUMS:
|
||||
ReactCommon: 5f9a24e64c1c3e2b719014f07cb2acf628983000
|
||||
ReactNativeIncallManager: 0d2cf9f4d50359728a30c08549762fe67a2efb81
|
||||
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
|
||||
RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc
|
||||
RNDeviceInfo: ab292735ad4fccc5f2aec0c773f7a7f03c7073ae
|
||||
RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd
|
||||
RNDeviceInfo: 749f2e049dcd79e2e44f134f66b73a06951b5066
|
||||
RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8
|
||||
RNFBApp: d59efa0872fff4e27de03cca3c528c203a436ae5
|
||||
RNFBMessaging: 216693dd5ba4f18ba65fb39fc73a44a23c26190f
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: dec4645026e7401a0899f2846d864403478ff6a5
|
||||
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
||||
RNImageCropPicker: 14fe1c29298fb4018f3186f455c475ab107da332
|
||||
RNReanimated: f186e85d9f28c9383d05ca39e11dd194f59093ec
|
||||
RNScreens: 68fd1060f57dd1023880bf4c05d74784b5392789
|
||||
RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128
|
||||
RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
|
||||
RNShare: d82e10f6b7677f4b0048c23709bd04098d5aee6c
|
||||
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
|
||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||
|
@ -13,9 +13,6 @@
|
||||
"@bam.tech/react-native-image-resizer": "^3.0.5",
|
||||
"@braintree/sanitize-url": "^6.0.2",
|
||||
"@react-native-clipboard/clipboard": "^1.11.1",
|
||||
"@react-native-community/blur": "^4.3.2",
|
||||
"@react-native-firebase/app": "^17.2.0",
|
||||
"@react-native-firebase/messaging": "^17.2.0",
|
||||
"@react-navigation/bottom-tabs": "^6.5.5",
|
||||
"@react-navigation/drawer": "^6.6.0",
|
||||
"@react-navigation/native": "^6.1.4",
|
||||
@ -46,7 +43,6 @@
|
||||
"react-native-screens": "^3.20.0",
|
||||
"react-native-share": "^8.2.2",
|
||||
"react-native-sqlite-storage": "^6.0.1",
|
||||
"react-native-unifiedpush-connector": "^0.1.5",
|
||||
"react-native-vector-icons": "^9.2.0",
|
||||
"react-native-video": "^5.2.1",
|
||||
"react-native-webrtc": "^118.0.2",
|
||||
|
@ -57,24 +57,7 @@ export function Admin() {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{ Platform.OS !== 'ios' && (
|
||||
<View style={styles.tos}>
|
||||
<TouchableOpacity style={styles.viewterms} onPress={actions.showTerms}>
|
||||
<Text style={styles.viewtermstext}>{ state.strings.terms }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.agreeterms} onPress={() => actions.agree(!state.agree)}>
|
||||
{ state.agree && (
|
||||
<MatIcons name={'checkbox-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
{ !state.agree && (
|
||||
<MatIcons name={'checkbox-blank-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
<Text style={styles.agreetermstext}>{ state.strings.agree }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{ state.enabled && (Platform.OS === 'ios' || state.agree) && (
|
||||
{ state.enabled && (
|
||||
<TouchableOpacity style={styles.reset} onPress={admin}>
|
||||
{ state.busy && (
|
||||
<ActivityIndicator size="small" color="#ffffff" />
|
||||
@ -84,7 +67,7 @@ export function Admin() {
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ (!state.enabled || (Platform.OS !== 'ios' && !state.agree)) && (
|
||||
{ !state.enabled && (
|
||||
<View style={styles.noreset}>
|
||||
<Text style={styles.noresettext}>{ state.strings.access }</Text>
|
||||
</View>
|
||||
|
@ -141,26 +141,8 @@ export function Create() {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{ Platform.OS !== 'ios' && (
|
||||
<View style={styles.tos}>
|
||||
<TouchableOpacity style={styles.viewterms} onPress={actions.showTerms}>
|
||||
<Text style={styles.viewtermstext}>{ state.strings.terms }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.agreeterms} onPress={() => actions.agree(!state.agree)}>
|
||||
{ state.agree && (
|
||||
<MatIcons name={'checkbox-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
{ !state.agree && (
|
||||
<MatIcons name={'checkbox-blank-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
<Text style={styles.agreetermstext}>{ state.strings.agree }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View style={styles.buttons}>
|
||||
{ state.enabled && (Platform.OS === 'ios' || state.agree) && (
|
||||
{ state.enabled && (
|
||||
<TouchableOpacity style={styles.create} onPress={create}>
|
||||
{ state.busy && (
|
||||
<ActivityIndicator size="small" color="#ffffff" />
|
||||
@ -170,7 +152,7 @@ export function Create() {
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ (!state.enabled || (Platform.OS !== 'ios' && !state.agree)) && (
|
||||
{ !state.enabled && (
|
||||
<View style={styles.nocreate}>
|
||||
<Text style={styles.nocreatetext}>{ state.strings.create }</Text>
|
||||
</View>
|
||||
|
@ -65,24 +65,7 @@ export function Login() {
|
||||
</View>
|
||||
)}
|
||||
|
||||
{ Platform.OS !== 'ios' && (
|
||||
<View style={styles.tos}>
|
||||
<TouchableOpacity style={styles.viewterms} onPress={actions.showTerms}>
|
||||
<Text style={styles.viewtermstext}>{ state.strings.terms }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.agreeterms} onPress={() => actions.agree(!state.agree)}>
|
||||
{ state.agree && (
|
||||
<MatIcons name={'checkbox-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
{ !state.agree && (
|
||||
<MatIcons name={'checkbox-blank-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
<Text style={styles.agreetermstext}>{ state.strings.agree }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{ state.enabled && (Platform.OS === 'ios' || state.agree) && (
|
||||
{ state.enabled && (
|
||||
<TouchableOpacity style={styles.login} onPress={login}>
|
||||
{ state.busy && (
|
||||
<ActivityIndicator size="small" color="#ffffff" />
|
||||
@ -92,7 +75,7 @@ export function Login() {
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ (!state.enabled || (Platform.OS !== 'ios' && !state.agree)) && (
|
||||
{ !state.enabled && (
|
||||
<View style={styles.nologin}>
|
||||
<Text style={styles.nologintext}>{ state.strings.login }</Text>
|
||||
</View>
|
||||
|
@ -48,24 +48,7 @@ export function Reset() {
|
||||
<View style={styles.space} />
|
||||
</View>
|
||||
|
||||
{ Platform.OS !== 'ios' && (
|
||||
<View style={styles.tos}>
|
||||
<TouchableOpacity style={styles.viewterms} onPress={actions.showTerms}>
|
||||
<Text style={styles.viewtermstext}>{ state.strings.terms }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.agreeterms} onPress={() => actions.agree(!state.agree)}>
|
||||
{ state.agree && (
|
||||
<MatIcons name={'checkbox-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
{ !state.agree && (
|
||||
<MatIcons name={'checkbox-blank-outline'} size={20} color={Colors.primary} />
|
||||
)}
|
||||
<Text style={styles.agreetermstext}>{state.strings.agree}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{ state.enabled && (Platform.OS === 'ios' || state.agree) && (
|
||||
{ state.enabled && (
|
||||
<TouchableOpacity style={styles.reset} onPress={reset}>
|
||||
{ state.busy && (
|
||||
<ActivityIndicator size="small" color="#ffffff" />
|
||||
@ -75,7 +58,7 @@ export function Reset() {
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ (!state.enabled || (Platform.OS !== 'ios' && !state.agree)) && (
|
||||
{ !state.enabled && (
|
||||
<View style={styles.noreset}>
|
||||
<Text style={styles.noresettext}>{ state.strings.access }</Text>
|
||||
</View>
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setAccountAccess(server, token, appName, appVersion, platform, deviceToken, pushType, notifications) {
|
||||
export async function setAccountAccess(server, token, appName, appVersion, platform, deviceToken, notifications) {
|
||||
const insecure = /^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(server);
|
||||
const protocol = insecure ? 'http' : 'https';
|
||||
|
||||
let access = await fetchWithTimeout(`${protocol}://${server}/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}&pushType=${pushType}`, { method: 'PUT', body: JSON.stringify(notifications) })
|
||||
let access = await fetchWithTimeout(`${protocol}://${server}/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}&pushType=up`, { method: 'PUT', body: JSON.stringify(notifications) })
|
||||
checkResponse(access)
|
||||
return await access.json()
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
import base64 from 'react-native-base64'
|
||||
|
||||
export async function setLogin(username, server, password, appName, appVersion, platform, deviceToken, pushType, notifications) {
|
||||
export async function setLogin(username, server, password, appName, appVersion, platform, deviceToken, notifications) {
|
||||
const insecure = /^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(server);
|
||||
const protocol = insecure ? 'http' : 'https';
|
||||
|
||||
let headers = new Headers()
|
||||
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
|
||||
let login = await fetchWithTimeout(`${protocol}://${server}/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}&pushType=${pushType}`, { method: 'POST', body: JSON.stringify(notifications), headers: headers })
|
||||
let login = await fetchWithTimeout(`${protocol}://${server}/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}&pushType=up`, { method: 'POST', body: JSON.stringify(notifications), headers: headers })
|
||||
checkResponse(login)
|
||||
return await login.json()
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ const DarkColors = {
|
||||
contentBase: '#000000',
|
||||
modalBase: '#1b1b1b',
|
||||
modalBorder: '#555555',
|
||||
modalOverlay: 'rgba(88,88,88,0.8)',
|
||||
modalOverlay: '#333333',
|
||||
headerBar: '#555555',
|
||||
primaryButton: '#448866',
|
||||
primaryButtonText: '#ffffff',
|
||||
|
@ -13,7 +13,6 @@ import { CardContext } from 'context/CardContext';
|
||||
import { ChannelContext } from 'context/ChannelContext';
|
||||
import { RingContext } from 'context/RingContext';
|
||||
import { getVersion, getApplicationName, getDeviceId } from 'react-native-device-info'
|
||||
import messaging from '@react-native-firebase/messaging';
|
||||
import { DeviceEventEmitter } from 'react-native';
|
||||
|
||||
export function useAppContext() {
|
||||
@ -36,7 +35,6 @@ export function useAppContext() {
|
||||
|
||||
const ws = useRef(null);
|
||||
const deviceToken = useRef(null);
|
||||
const pushType = useRef(null);
|
||||
const access = useRef(null);
|
||||
const init = useRef(false);
|
||||
|
||||
@ -44,32 +42,15 @@ export function useAppContext() {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
}
|
||||
|
||||
const setDeviceToken = async () => {
|
||||
if (!deviceToken.current) {
|
||||
try {
|
||||
const token = await messaging().getToken();
|
||||
if (!token) {
|
||||
throw new Error('null push token');
|
||||
}
|
||||
deviceToken.current = token;
|
||||
pushType.current = "fcm";
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
// select the unified token if available
|
||||
DeviceEventEmitter.addListener('unifiedPushURL', (e) => {
|
||||
deviceToken.current = e.endpoint;
|
||||
pushType.current = "up";
|
||||
});
|
||||
|
||||
(async () => {
|
||||
await setDeviceToken();
|
||||
access.current = await store.actions.init();
|
||||
if (access.current) {
|
||||
await setSession();
|
||||
@ -118,62 +99,46 @@ export function useAppContext() {
|
||||
if (!init.current || access.current) {
|
||||
throw new Error('invalid session state');
|
||||
}
|
||||
await setDeviceToken();
|
||||
updateState({ loggedOut: false });
|
||||
await addAccount(server, username, password, token);
|
||||
const session = await setLogin(username, server, password, getApplicationName(), getVersion(), getDeviceId(), deviceToken.current, pushType.current, notifications)
|
||||
const session = await setLogin(username, server, password, getApplicationName(), getVersion(), getDeviceId(), deviceToken.current, notifications)
|
||||
access.current = { loginTimestamp: session.created, server, token: session.appToken, guid: session.guid };
|
||||
await store.actions.setSession(access.current);
|
||||
await setSession();
|
||||
if (session.pushSupported) {
|
||||
messaging().requestPermission().then(status => {})
|
||||
}
|
||||
},
|
||||
access: async (server, token) => {
|
||||
if (!init.current || access.current) {
|
||||
throw new Error('invalid session state');
|
||||
}
|
||||
await setDeviceToken();
|
||||
updateState({ loggedOut: false });
|
||||
const session = await setAccountAccess(server, token, getApplicationName(), getVersion(), getDeviceId(), deviceToken.current, pushType.current, notifications);
|
||||
const session = await setAccountAccess(server, token, getApplicationName(), getVersion(), getDeviceId(), deviceToken.current, notifications);
|
||||
access.current = { loginTimestamp: session.created, server, token: session.appToken, guid: session.guid };
|
||||
await store.actions.setSession(access.current);
|
||||
await setSession();
|
||||
if (session.pushSupported) {
|
||||
messaging().requestPermission().then(status => {})
|
||||
}
|
||||
},
|
||||
login: async (username, password) => {
|
||||
if (!init.current || access.current) {
|
||||
throw new Error('invalid session state');
|
||||
}
|
||||
await setDeviceToken();
|
||||
updateState({ loggedOut: false });
|
||||
const acc = username.includes('/') ? username.split('/') : username.split('@');
|
||||
const session = await setLogin(acc[0], acc[1], password, getApplicationName(), getVersion(), getDeviceId(), deviceToken.current, pushType.current, notifications)
|
||||
const session = await setLogin(acc[0], acc[1], password, getApplicationName(), getVersion(), getDeviceId(), deviceToken.current, notifications)
|
||||
access.current = { loginTimestamp: session.created, server: acc[1], token: session.appToken, guid: session.guid };
|
||||
await store.actions.setSession(access.current);
|
||||
await setSession();
|
||||
if (session.pushSupported) {
|
||||
messaging().requestPermission().then(status => {})
|
||||
}
|
||||
},
|
||||
logout: async () => {
|
||||
if (!access.current) {
|
||||
throw new Error('invalid session state');
|
||||
}
|
||||
updateState({ loggingOut: true });
|
||||
try {
|
||||
if (pushType.current == "fcm") {
|
||||
await messaging().deleteToken();
|
||||
deviceToken.current = await messaging().getToken();
|
||||
}
|
||||
const { server, token } = access.current || {};
|
||||
await clearLogin(server, token);
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
updateState({ loggingOut: true });
|
||||
await clearSession();
|
||||
access.current = null;
|
||||
await store.actions.clearSession();
|
||||
|
@ -7,7 +7,6 @@ import { styles } from './Dashboard.styled';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useDashboard } from './useDashboard.hook';
|
||||
import { Logo } from 'utils/Logo';
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
import { InputField } from 'utils/InputField';
|
||||
|
||||
export function Dashboard(props) {
|
||||
@ -133,149 +132,146 @@ export function Dashboard(props) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideEditConfig}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={'dark'} blurAmount={2} reducedTransparencyFallbackColor='black' />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalHeaderText}>{ state.strings.settings }</Text>
|
||||
</View>
|
||||
<ScrollView style={styles.modalBody}>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.federatedHost}
|
||||
value={state.domain}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setDomain}
|
||||
/>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.storageLimit}
|
||||
value={state.storage}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
keyboardType={'numeric'}
|
||||
onChangeText={actions.setStorage}
|
||||
/>
|
||||
|
||||
<Text style={styles.modalLabel}>{ state.strings.keyType }</Text>
|
||||
<View style={styles.keyType}>
|
||||
<TouchableOpacity style={styles.optionLeft} activeOpacity={1}
|
||||
onPress={() => actions.setKeyType('RSA2048')}>
|
||||
{ state.keyType === 'RSA2048' && (
|
||||
<View style={styles.selected} />
|
||||
)}
|
||||
{ state.keyType === 'RSA4096' && (
|
||||
<View style={styles.radio} />
|
||||
)}
|
||||
<Text style={styles.option}>RSA 2048</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.optionRight} activeOpacity={1}
|
||||
onPress={() => actions.setKeyType('RSA4096')}>
|
||||
{ state.keyType === 'RSA2048' && (
|
||||
<View style={styles.radio} />
|
||||
)}
|
||||
{ state.keyType === 'RSA4096' && (
|
||||
<View style={styles.selected} />
|
||||
)}
|
||||
<Text style={styles.option}>RSA 4096</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setPushSupported(!state.pushSupported)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableNotifications }</Text>
|
||||
<Switch style={styles.switch} value={state.pushSupported}
|
||||
onValueChange={actions.setPushSupported} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
|
||||
{ state.transformSupported && (
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setAllowUnsealed(!state.allowUnsealed)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.allowUnsealed }</Text>
|
||||
<Switch style={styles.switch} value={state.allowUnsealed}
|
||||
onValueChange={actions.setAllowUnsealed} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
<View style={styles.label}></View>
|
||||
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableImage(!state.enableImage)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableImage }</Text>
|
||||
<Switch style={styles.switch} value={state.enableImage}
|
||||
onValueChange={actions.setEnableImage} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableAudio(!state.enableAudio)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableAudio }</Text>
|
||||
<Switch style={styles.switch} value={state.enableAudio}
|
||||
onValueChange={actions.setEnableAudio} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableVideo(!state.enableVideo)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableVideo }</Text>
|
||||
<Switch style={styles.switch} value={state.enableVideo}
|
||||
onValueChange={actions.setEnableVideo} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableBinary(!state.enableBinary)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableBinary }</Text>
|
||||
<Switch style={styles.switch} value={state.enableBinary}
|
||||
onValueChange={actions.setEnableBinary} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.label}></View>
|
||||
<TouchableOpacity style={styles.ice} activeOpacity={1}
|
||||
onPress={() => actions.setEnableIce(!state.enableIce)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableCalls }</Text>
|
||||
<Switch style={styles.switch} value={state.enableIce}
|
||||
onValueChange={actions.setEnableIce} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.relayUrl}
|
||||
value={state.iceUrl}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
disabled={!state.enableIce}
|
||||
onChangeText={actions.setIceUrl}
|
||||
/>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.relayUsername}
|
||||
value={state.iceUsername}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
disabled={!state.enableIce}
|
||||
onChangeText={actions.setIceUsername}
|
||||
/>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.relayPassword}
|
||||
value={state.icePassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
disabled={!state.enableIce}
|
||||
onChangeText={actions.setIcePassword}
|
||||
/>
|
||||
|
||||
<View style={styles.pad} />
|
||||
|
||||
</ScrollView>
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.cancel} onPress={actions.hideEditConfig}>
|
||||
<Text style={styles.cancelText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.save} onPress={saveConfig}>
|
||||
<Text style={styles.saveText}>{ state.strings.save }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalHeaderText}>{ state.strings.settings }</Text>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
<ScrollView style={styles.modalBody}>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.federatedHost}
|
||||
value={state.domain}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setDomain}
|
||||
/>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.storageLimit}
|
||||
value={state.storage}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
keyboardType={'numeric'}
|
||||
onChangeText={actions.setStorage}
|
||||
/>
|
||||
|
||||
<Text style={styles.modalLabel}>{ state.strings.keyType }</Text>
|
||||
<View style={styles.keyType}>
|
||||
<TouchableOpacity style={styles.optionLeft} activeOpacity={1}
|
||||
onPress={() => actions.setKeyType('RSA2048')}>
|
||||
{ state.keyType === 'RSA2048' && (
|
||||
<View style={styles.selected} />
|
||||
)}
|
||||
{ state.keyType === 'RSA4096' && (
|
||||
<View style={styles.radio} />
|
||||
)}
|
||||
<Text style={styles.option}>RSA 2048</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.optionRight} activeOpacity={1}
|
||||
onPress={() => actions.setKeyType('RSA4096')}>
|
||||
{ state.keyType === 'RSA2048' && (
|
||||
<View style={styles.radio} />
|
||||
)}
|
||||
{ state.keyType === 'RSA4096' && (
|
||||
<View style={styles.selected} />
|
||||
)}
|
||||
<Text style={styles.option}>RSA 4096</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setPushSupported(!state.pushSupported)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableNotifications }</Text>
|
||||
<Switch style={styles.switch} value={state.pushSupported}
|
||||
onValueChange={actions.setPushSupported} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
|
||||
{ state.transformSupported && (
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setAllowUnsealed(!state.allowUnsealed)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.allowUnsealed }</Text>
|
||||
<Switch style={styles.switch} value={state.allowUnsealed}
|
||||
onValueChange={actions.setAllowUnsealed} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
<View style={styles.label}></View>
|
||||
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableImage(!state.enableImage)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableImage }</Text>
|
||||
<Switch style={styles.switch} value={state.enableImage}
|
||||
onValueChange={actions.setEnableImage} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableAudio(!state.enableAudio)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableAudio }</Text>
|
||||
<Switch style={styles.switch} value={state.enableAudio}
|
||||
onValueChange={actions.setEnableAudio} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableVideo(!state.enableVideo)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableVideo }</Text>
|
||||
<Switch style={styles.switch} value={state.enableVideo}
|
||||
onValueChange={actions.setEnableVideo} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.media} activeOpacity={1}
|
||||
onPress={() => actions.setEnableBinary(!state.enableBinary)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableBinary }</Text>
|
||||
<Switch style={styles.switch} value={state.enableBinary}
|
||||
onValueChange={actions.setEnableBinary} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.label}></View>
|
||||
<TouchableOpacity style={styles.ice} activeOpacity={1}
|
||||
onPress={() => actions.setEnableIce(!state.enableIce)}>
|
||||
<Text style={styles.modalLabel}>{ state.strings.enableCalls }</Text>
|
||||
<Switch style={styles.switch} value={state.enableIce}
|
||||
onValueChange={actions.setEnableIce} trackColor={styles.track}/>
|
||||
</TouchableOpacity>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.relayUrl}
|
||||
value={state.iceUrl}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
disabled={!state.enableIce}
|
||||
onChangeText={actions.setIceUrl}
|
||||
/>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.relayUsername}
|
||||
value={state.iceUsername}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
disabled={!state.enableIce}
|
||||
onChangeText={actions.setIceUsername}
|
||||
/>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.relayPassword}
|
||||
value={state.icePassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
disabled={!state.enableIce}
|
||||
onChangeText={actions.setIcePassword}
|
||||
/>
|
||||
|
||||
<View style={styles.pad} />
|
||||
|
||||
</ScrollView>
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.cancel} onPress={actions.hideEditConfig}>
|
||||
<Text style={styles.cancelText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.save} onPress={saveConfig}>
|
||||
<Text style={styles.saveText}>{ state.strings.save }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
@ -286,24 +282,21 @@ export function Dashboard(props) {
|
||||
onRequestClose={actions.hideAddUser}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={'dark'} blurAmount={2} reducedTransparencyFallbackColor='black' />
|
||||
<View style={styles.modalBase}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalHeaderText}>{ state.strings.createAccount }</Text>
|
||||
</View>
|
||||
<View style={styles.accessToken}>
|
||||
<Text style={styles.tokenLabel}>{ state.strings.token }</Text>
|
||||
<TouchableOpacity style={styles.copy} onPress={() => Clipboard.setString(state.createToken)}>
|
||||
<Text style={styles.token}>{ state.createToken }</Text>
|
||||
<AntIcon style={styles.icon} name={'copy1'} size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideAddUser}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalHeaderText}>{ state.strings.createAccount }</Text>
|
||||
</View>
|
||||
<View style={styles.accessToken}>
|
||||
<Text style={styles.tokenLabel}>{ state.strings.token }</Text>
|
||||
<TouchableOpacity style={styles.copy} onPress={() => Clipboard.setString(state.createToken)}>
|
||||
<Text style={styles.token}>{ state.createToken }</Text>
|
||||
<AntIcon style={styles.icon} name={'copy1'} size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideAddUser}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -317,24 +310,21 @@ export function Dashboard(props) {
|
||||
onRequestClose={actions.hideAccessUser}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={'dark'} blurAmount={2} reducedTransparencyFallbackColor='black' />
|
||||
<View style={styles.modalBase}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalHeaderText}>{ state.strings.accessAccount }</Text>
|
||||
</View>
|
||||
<View style={styles.accessToken}>
|
||||
<Text style={styles.tokenLabel}>{ state.strings.token }</Text>
|
||||
<TouchableOpacity style={styles.copy} onPress={() => Clipboard.setString(state.accessToken)}>
|
||||
<Text style={styles.token}>{ state.accessToken }</Text>
|
||||
<AntIcon style={styles.icon} name={'copy1'} size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideAccessUser}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalHeaderText}>{ state.strings.accessAccount }</Text>
|
||||
</View>
|
||||
<View style={styles.accessToken}>
|
||||
<Text style={styles.tokenLabel}>{ state.strings.token }</Text>
|
||||
<TouchableOpacity style={styles.copy} onPress={() => Clipboard.setString(state.accessToken)}>
|
||||
<Text style={styles.token}>{ state.accessToken }</Text>
|
||||
<AntIcon style={styles.icon} name={'copy1'} size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideAccessUser}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
@ -174,6 +174,11 @@ export const styles = StyleSheet.create({
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
},
|
||||
modalBody: {
|
||||
padding: 16,
|
||||
|
@ -32,7 +32,6 @@ import lightSplash from 'images/session.png';
|
||||
import darkSplash from 'images/darksess.png';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { getLanguageStrings } from 'constants/Strings';
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
|
||||
const ConversationStack = createStackNavigator();
|
||||
const ProfileStack = createStackNavigator();
|
||||
@ -494,7 +493,7 @@ export function Session({ sharing, clearSharing }) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
>
|
||||
<View style={styles.ringBase}>
|
||||
<BlurView style={styles.ringBase} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.blur} />
|
||||
<View style={styles.ringFrame}>
|
||||
{ ringing }
|
||||
</View>
|
||||
|
@ -7,6 +7,11 @@ export const styles = StyleSheet.create({
|
||||
height: '100%',
|
||||
backgroundColor: Colors.screenBase,
|
||||
},
|
||||
blur: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
},
|
||||
container: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
|
@ -6,7 +6,6 @@ import { useChannels } from './useChannels.hook';
|
||||
import { Colors } from 'constants/Colors';
|
||||
import { ChannelItem } from './channelItem/ChannelItem';
|
||||
import { AddMember } from './addMember/AddMember';
|
||||
import { BlurView } from '@react-native-community/blur';
|
||||
import { InputField } from 'utils/InputField';
|
||||
|
||||
export function Channels({ cardId, channelId, navigation, openConversation, dmChannel, shareChannel }) {
|
||||
@ -102,60 +101,56 @@ export function Channels({ cardId, channelId, navigation, openConversation, dmCh
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideAdding}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.addHeader}>{ state.strings.newTopic }</Text>
|
||||
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.addHeader}>{ state.strings.newTopic }</Text>
|
||||
<InputField
|
||||
label={state.strings.subject}
|
||||
value={state.addSubject}
|
||||
autoCapitalize={'words'}
|
||||
spellCheck={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setAddSubject}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.subject}
|
||||
value={state.addSubject}
|
||||
autoCapitalize={'words'}
|
||||
spellCheck={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setAddSubject}
|
||||
/>
|
||||
|
||||
{ state.contacts.length == 0 && (
|
||||
<View style={styles.emptyMembers}>
|
||||
<Text style={styles.notfoundtext}>{ state.strings.noContacts }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.contacts.length > 0 && (
|
||||
<FlatList style={styles.addMembers}
|
||||
data={state.contacts}
|
||||
renderItem={({ item }) => <AddMember members={state.addMembers} item={item}
|
||||
setCard={actions.setAddMember} clearCard={actions.clearAddMember} />}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.addControls}>
|
||||
<View style={styles.sealed}>
|
||||
{ state.sealable && state.allowUnsealed && (
|
||||
<>
|
||||
<Switch style={styles.switch} trackColor={styles.track}
|
||||
value={state.sealed} onValueChange={actions.setSealed} />
|
||||
<Text style={styles.sealedText}>{ state.strings.sealed }</Text>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
<TouchableOpacity style={styles.cancel} onPress={actions.hideAdding}>
|
||||
<Text style={styles.cancelText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.save} onPress={addChannel}>
|
||||
{ state.busy && (
|
||||
<ActivityIndicator color={Colors.text} />
|
||||
)}
|
||||
{ !state.busy && (
|
||||
<Text style={styles.saveText}>{ state.strings.create }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
{ state.contacts.length == 0 && (
|
||||
<View style={styles.emptyMembers}>
|
||||
<Text style={styles.empty}>{ state.strings.noContacts }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.contacts.length > 0 && (
|
||||
<FlatList style={styles.addMembers}
|
||||
data={state.contacts}
|
||||
renderItem={({ item }) => <AddMember members={state.addMembers} item={item}
|
||||
setCard={actions.setAddMember} clearCard={actions.clearAddMember} />}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.addControls}>
|
||||
<View style={styles.sealed}>
|
||||
{ state.sealable && state.allowUnsealed && (
|
||||
<>
|
||||
<Switch style={styles.switch} trackColor={styles.track}
|
||||
value={state.sealed} onValueChange={actions.setSealed} />
|
||||
<Text style={styles.sealedText}>{ state.strings.sealed }</Text>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
<TouchableOpacity style={styles.cancel} onPress={actions.hideAdding}>
|
||||
<Text style={styles.cancelText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.save} onPress={addChannel}>
|
||||
{ state.busy && (
|
||||
<ActivityIndicator color={Colors.text} />
|
||||
)}
|
||||
{ !state.busy && (
|
||||
<Text style={styles.saveText}>{ state.strings.create }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
</View>
|
||||
);
|
||||
|
@ -201,18 +201,13 @@ export const styles = StyleSheet.create({
|
||||
transform: [{ scaleX: .7 }, { scaleY: .7 }],
|
||||
},
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
modalBase: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.modalBase,
|
||||
|
@ -8,7 +8,6 @@ import Ionicons from 'react-native-vector-icons/AntDesign';
|
||||
import { Logo } from 'utils/Logo';
|
||||
import { AddTopic } from './addTopic/AddTopic';
|
||||
import { TopicItem } from './topicItem/TopicItem';
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
|
||||
export function Conversation({ navigation, cardId, channelId, closeConversation, openDetails, shareIntent, setShareIntent }) {
|
||||
|
||||
@ -123,7 +122,7 @@ export function Conversation({ navigation, cardId, channelId, closeConversation,
|
||||
onRequestClose={actions.hideEdit}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.blur} />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.editMessage }</Text>
|
||||
|
@ -10,6 +10,11 @@ export const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
flexShrink: 1,
|
||||
},
|
||||
blur: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
},
|
||||
more: {
|
||||
marginTop: 8,
|
||||
},
|
||||
|
@ -13,7 +13,6 @@ import { VideoFile } from './videoFile/VideoFile';
|
||||
import { AudioFile } from './audioFile/AudioFile';
|
||||
import { ImageFile } from './imageFile/ImageFile';
|
||||
import { BinaryFile } from './binaryFile/BinaryFile';
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
|
||||
export function AddTopic({ contentKey, shareIntent, setShareIntent }) {
|
||||
|
||||
@ -231,48 +230,45 @@ export function AddTopic({ contentKey, shareIntent, setShareIntent }) {
|
||||
onRequestClose={actions.hideFontSize}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.fontSize }</Text>
|
||||
<View style={styles.editSize}>
|
||||
{ state.size === 'small' && (
|
||||
<View style={styles.selected}>
|
||||
<Text style={styles.selectedText}>{ state.strings.small }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.size !== 'small' && (
|
||||
<TouchableOpacity style={styles.option} onPress={() => actions.setFontSize('small')}>
|
||||
<Text style={styles.optionText}>{ state.strings.small }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.size === 'medium' && (
|
||||
<View style={styles.selected}>
|
||||
<Text style={styles.selectedText}>{ state.strings.medium }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.size !== 'medium' && (
|
||||
<TouchableOpacity style={styles.option} onPress={() => actions.setFontSize('medium')}>
|
||||
<Text style={styles.optionText}>{ state.strings.medium }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.size === 'large' && (
|
||||
<View style={styles.selected}>
|
||||
<Text style={styles.selectedText}>{ state.strings.large }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.size !== 'large' && (
|
||||
<TouchableOpacity style={styles.option} onPress={() => actions.setFontSize('large')}>
|
||||
<Text style={styles.optionText}>{ state.strings.large }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.editControls}>
|
||||
<View style={styles.selection} />
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideFontSize}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.fontSize }</Text>
|
||||
<View style={styles.editSize}>
|
||||
{ state.size === 'small' && (
|
||||
<View style={styles.selected}>
|
||||
<Text style={styles.selectedText}>{ state.strings.small }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.size !== 'small' && (
|
||||
<TouchableOpacity style={styles.option} onPress={() => actions.setFontSize('small')}>
|
||||
<Text style={styles.optionText}>{ state.strings.small }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{ state.size === 'medium' && (
|
||||
<View style={styles.selected}>
|
||||
<Text style={styles.selectedText}>{ state.strings.medium }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.size !== 'medium' && (
|
||||
<TouchableOpacity style={styles.option} onPress={() => actions.setFontSize('medium')}>
|
||||
<Text style={styles.optionText}>{ state.strings.medium }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.size === 'large' && (
|
||||
<View style={styles.selected}>
|
||||
<Text style={styles.selectedText}>{ state.strings.large }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.size !== 'large' && (
|
||||
<TouchableOpacity style={styles.option} onPress={() => actions.setFontSize('large')}>
|
||||
<Text style={styles.optionText}>{ state.strings.large }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.editControls}>
|
||||
<View style={styles.selection} />
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideFontSize}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -285,27 +281,24 @@ export function AddTopic({ contentKey, shareIntent, setShareIntent }) {
|
||||
onRequestClose={actions.hideFontColor}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.fontColor }</Text>
|
||||
<View style={styles.editColor}>
|
||||
<ColorPicker
|
||||
color={state.color}
|
||||
onColorChange={actions.setFontColor}
|
||||
onColorChangeComplete={actions.setFontColor}
|
||||
swatched={false}
|
||||
style={{flex: 1, padding: 8}} />
|
||||
</View>
|
||||
<View style={styles.editControls}>
|
||||
<View style={styles.selection}>
|
||||
<Text style={styles.selectionText}>{ state.strings.selectedColor }</Text>
|
||||
<View style={{ marginLeft: 6, borderRadius: 4, width: 16, height: 16, backgroundColor: state.color }} />
|
||||
</View>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideFontColor}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.fontColor }</Text>
|
||||
<View style={styles.editColor}>
|
||||
<ColorPicker
|
||||
color={state.color}
|
||||
onColorChange={actions.setFontColor}
|
||||
onColorChangeComplete={actions.setFontColor}
|
||||
swatched={false}
|
||||
style={{flex: 1, padding: 8}} />
|
||||
</View>
|
||||
<View style={styles.editControls}>
|
||||
<View style={styles.selection}>
|
||||
<Text style={styles.selectionText}>{ state.strings.selectedColor }</Text>
|
||||
<View style={{ marginLeft: 6, borderRadius: 4, width: 16, height: 16, backgroundColor: state.color }} />
|
||||
</View>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideFontColor}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
@ -136,19 +136,14 @@ export const styles = StyleSheet.create({
|
||||
selectionText: {
|
||||
color: Colors.text,
|
||||
},
|
||||
modalOverlay: {
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
modalBase: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.modalBase,
|
||||
|
@ -7,7 +7,6 @@ import AntIcons from 'react-native-vector-icons/AntDesign';
|
||||
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import Colors from 'constants/Colors';
|
||||
import { MemberItem } from './memberItem/MemberItem';
|
||||
import { BlurView } from '@react-native-community/blur';
|
||||
import { InputField } from 'utils/InputField';
|
||||
|
||||
export function Details({ channel, clearConversation }) {
|
||||
@ -162,7 +161,7 @@ export function Details({ channel, clearConversation }) {
|
||||
onRequestClose={actions.hideEditSubject}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.blur} />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.editSubject }</Text>
|
||||
@ -196,24 +195,21 @@ export function Details({ channel, clearConversation }) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideEditMembers}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.topicMembers }</Text>
|
||||
<FlatList style={styles.editMembers}
|
||||
data={state.connected}
|
||||
renderItem={({ item }) => <MemberItem item={item} toggle={toggle} />}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
<View style={styles.editControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideEditMembers}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.editHeader}>{ state.strings.topicMembers }</Text>
|
||||
<FlatList style={styles.editMembers}
|
||||
data={state.connected}
|
||||
renderItem={({ item }) => <MemberItem item={item} toggle={toggle} />}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
<View style={styles.editControls}>
|
||||
<TouchableOpacity style={styles.close} onPress={actions.hideEditMembers}>
|
||||
<Text style={styles.closeText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
</View>
|
||||
|
@ -183,16 +183,11 @@ export const styles = StyleSheet.create({
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
modalBase: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.modalBase,
|
||||
|
@ -3,7 +3,6 @@ import { useState } from 'react';
|
||||
import AntIcons from 'react-native-vector-icons/AntDesign';
|
||||
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import ImagePicker from 'react-native-image-crop-picker'
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
import { FloatingLabelInput } from 'react-native-floating-label-input';
|
||||
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { Menu, MenuOptions, MenuOption, MenuTrigger } from 'react-native-popup-menu';
|
||||
@ -201,64 +200,61 @@ export function Profile({ drawer }) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideDetails}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideDetails}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.editDetails }</Text>
|
||||
|
||||
<InputField
|
||||
label={state.strings.name}
|
||||
value={state.detailName}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
multiline={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setDetailName}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.location}
|
||||
value={state.detailLocation}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
multiline={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setDetailLocation}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.description}
|
||||
value={state.detailDescription}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
multiline={true}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setDetailDescription}
|
||||
/>
|
||||
|
||||
<View style={styles.buttons}>
|
||||
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={actions.hideDetails}>
|
||||
<Text style={styles.cancelButtonText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.saveButton} activeOpacity={1} onPress={saveDetails}>
|
||||
{ busyDetail && (
|
||||
<ActivityIndicator animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busyDetail && (
|
||||
<Text style={styles.saveButtonText}>{ state.strings.save }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideDetails}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.editDetails }</Text>
|
||||
|
||||
<InputField
|
||||
label={state.strings.name}
|
||||
value={state.detailName}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
multiline={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setDetailName}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.location}
|
||||
value={state.detailLocation}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
multiline={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setDetailLocation}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.description}
|
||||
value={state.detailDescription}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
multiline={true}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setDetailDescription}
|
||||
/>
|
||||
|
||||
<View style={styles.buttons}>
|
||||
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={actions.hideDetails}>
|
||||
<Text style={styles.cancelButtonText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.saveButton} activeOpacity={1} onPress={saveDetails}>
|
||||
{ busyDetail && (
|
||||
<ActivityIndicator animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busyDetail && (
|
||||
<Text style={styles.saveButtonText}>{ state.strings.save }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
</>
|
||||
|
@ -281,16 +281,11 @@ export const styles = StyleSheet.create({
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
modalBase: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center',
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.modalBase,
|
||||
|
@ -6,7 +6,6 @@ import { styles } from './Settings.styled';
|
||||
import { useSettings } from './useSettings.hook';
|
||||
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import Colors from 'constants/Colors';
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
import { InputField } from 'utils/InputField';
|
||||
import { Logo } from 'utils/Logo';
|
||||
|
||||
@ -427,175 +426,172 @@ export function Settings({ drawer }) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideEditSeal}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideEditSeal}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.sealedTopics }</Text>
|
||||
{ !state.sealEnabled && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealUnset }</Text>
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideEditSeal}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.sealedTopics }</Text>
|
||||
{ !state.sealEnabled && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealUnset }</Text>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.password}
|
||||
secret={true}
|
||||
value={state.sealPassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealPassword}
|
||||
/>
|
||||
|
||||
{ state.sealPassword && (
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.generateKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.generate }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ !state.sealPassword && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.generate }</Text>
|
||||
</View>
|
||||
)}
|
||||
<Text style={styles.delayMessage}>{ state.strings.delayMessage }</Text>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && !state.sealUnlocked && !state.sealRemove && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealLocked }</Text>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.password}
|
||||
secret={true}
|
||||
value={state.sealPassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealPassword}
|
||||
/>
|
||||
|
||||
{ state.sealPassword && (
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.unlockKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.unlock }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ !state.sealPassword && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.unlock }</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.showSealRemove}>
|
||||
<Text style={styles.dangerText}>{ state.strings.removeSeal }</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && state.sealUnlocked && !state.sealRemove && !state.sealUpdate && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealUnlocked }</Text>
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.disableKey)}>
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.password}
|
||||
secret={true}
|
||||
value={state.sealPassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealPassword}
|
||||
/>
|
||||
|
||||
{ state.sealPassword && (
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.generateKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.disable }</Text>
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.generate }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.showSealUpdate}>
|
||||
<Text style={styles.modeText}>{ state.strings.changeKey }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.showSealRemove}>
|
||||
<Text style={styles.dangerText}>{ state.strings.removeSeal }</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && state.sealRemove && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealDelete }</Text>
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.typeDelete}
|
||||
value={state.sealDelete}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealDelete}
|
||||
/>
|
||||
{ state.sealDelete === state.strings.deleteKey && (
|
||||
<TouchableOpacity style={styles.dangerButton} activeOpacity={1} onPress={() => sealAction(actions.removeKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.dangerButtonText}>{ state.strings.delete }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.sealDelete !== state.strings.deleteKey && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.delete }</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.hideSealRemove}>
|
||||
{ state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.disableSeal }</Text>
|
||||
)}
|
||||
{ !state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.unlockSeal }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && state.sealUnlocked && state.sealUpdate && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.changePassword }</Text>
|
||||
)}
|
||||
{ !state.sealPassword && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.generate }</Text>
|
||||
</View>
|
||||
)}
|
||||
<Text style={styles.delayMessage}>{ state.strings.delayMessage }</Text>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && !state.sealUnlocked && !state.sealRemove && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealLocked }</Text>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.password}
|
||||
isPassword={true}
|
||||
value={state.sealPassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealPassword}
|
||||
/>
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.password}
|
||||
secret={true}
|
||||
value={state.sealPassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealPassword}
|
||||
/>
|
||||
|
||||
{ state.sealPassword && (
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.updateKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.update }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ !state.sealPassword && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.update }</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.hideSealUpdate}>
|
||||
{ state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.disableSeal }</Text>
|
||||
{ state.sealPassword && (
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.unlockKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.unlockSeal }</Text>
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.unlock }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
)}
|
||||
{ !state.sealPassword && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.unlock }</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.showSealRemove}>
|
||||
<Text style={styles.dangerText}>{ state.strings.removeSeal }</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && state.sealUnlocked && !state.sealRemove && !state.sealUpdate && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealUnlocked }</Text>
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.disableKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.disable }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.showSealUpdate}>
|
||||
<Text style={styles.modeText}>{ state.strings.changeKey }</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.showSealRemove}>
|
||||
<Text style={styles.dangerText}>{ state.strings.removeSeal }</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && state.sealRemove && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.sealDelete }</Text>
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.typeDelete}
|
||||
value={state.sealDelete}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealDelete}
|
||||
/>
|
||||
{ state.sealDelete === state.strings.deleteKey && (
|
||||
<TouchableOpacity style={styles.dangerButton} activeOpacity={1} onPress={() => sealAction(actions.removeKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.dangerButtonText}>{ state.strings.delete }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.sealDelete !== state.strings.deleteKey && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.delete }</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.hideSealRemove}>
|
||||
{ state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.disableSeal }</Text>
|
||||
)}
|
||||
{ !state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.unlockSeal }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
{ state.sealEnabled && state.sealUnlocked && state.sealUpdate && (
|
||||
<>
|
||||
<Text style={styles.modalDescription}>{ state.strings.changePassword }</Text>
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.password}
|
||||
isPassword={true}
|
||||
value={state.sealPassword}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setSealPassword}
|
||||
/>
|
||||
|
||||
{ state.sealPassword && (
|
||||
<TouchableOpacity style={styles.enabledButton} activeOpacity={1} onPress={() => sealAction(actions.updateKey)}>
|
||||
{ busy && (
|
||||
<ActivityIndicator style={styles.modalBusy} animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
{ !busy && (
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.update }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ !state.sealPassword && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.update }</Text>
|
||||
</View>
|
||||
)}
|
||||
<TouchableOpacity activeOpacity={1} onPress={actions.hideSealUpdate}>
|
||||
{ state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.disableSeal }</Text>
|
||||
)}
|
||||
{ !state.sealUnlocked && (
|
||||
<Text style={styles.modeText}>{ state.strings.unlockSeal }</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
@ -605,62 +601,59 @@ export function Settings({ drawer }) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideLogin}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideLogin}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.changeLogin }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
|
||||
<Text textAlign={'center'} style={styles.modalDescription}>{ state.strings.changeMessage }</Text>
|
||||
|
||||
<InputField
|
||||
label={state.strings.username}
|
||||
value={state.username}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setUsername}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.password}
|
||||
value={state.password}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setPassword}
|
||||
secret={true}
|
||||
/>
|
||||
|
||||
<View style={styles.availableStatus}>
|
||||
{ state.validated && !state.available && (
|
||||
<Text style={styles.notAvailable}>{ state.strings.notAvailable }</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.hintButtons}>
|
||||
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={actions.hideLogin}>
|
||||
<Text style={styles.cancelButtonText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
{ (!state.available || !state.password || !state.validated || !state.username) && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.update }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.available && state.password && state.validated && state.username && (
|
||||
<TouchableOpacity style={styles.promptButton} activeOpacity={1} onPress={changeLogin}>
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.update }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideLogin}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.changeLogin }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
|
||||
<Text textAlign={'center'} style={styles.modalDescription}>{ state.strings.changeMessage }</Text>
|
||||
|
||||
<InputField
|
||||
label={state.strings.username}
|
||||
value={state.username}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setUsername}
|
||||
/>
|
||||
|
||||
<InputField
|
||||
label={state.strings.password}
|
||||
value={state.password}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
style={styles.field}
|
||||
onChangeText={actions.setPassword}
|
||||
secret={true}
|
||||
/>
|
||||
|
||||
<View style={styles.availableStatus}>
|
||||
{ state.validated && !state.available && (
|
||||
<Text style={styles.notAvailable}>{ state.strings.notAvailable }</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.hintButtons}>
|
||||
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={actions.hideLogin}>
|
||||
<Text style={styles.cancelButtonText}>{ state.strings.cancel }</Text>
|
||||
</TouchableOpacity>
|
||||
{ (!state.available || !state.password || !state.validated || !state.username) && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.update }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.available && state.password && state.validated && state.username && (
|
||||
<TouchableOpacity style={styles.promptButton} activeOpacity={1} onPress={changeLogin}>
|
||||
<Text style={styles.enabledButtonText}>{ state.strings.update }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
@ -670,41 +663,38 @@ export function Settings({ drawer }) {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideDelete}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<KeyboardAvoidingView style={styles.modalBase} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideDelete}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.deleteAccount }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.typeDelete}
|
||||
value={state.confirm}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setConfirm}
|
||||
/>
|
||||
|
||||
<View style={styles.buttons}>
|
||||
{ state.confirm === state.strings.deleteKey && (
|
||||
<TouchableOpacity style={styles.dangerButton} activeOpacity={1} onPress={deleteAccount}>
|
||||
<Text style={styles.dangerButtonText}>{ state.strings.delete }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.confirm !== state.strings.deleteKey && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.delete }</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<KeyboardAvoidingView style={styles.modalOverlay} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideDelete}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.deleteAccount }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
|
||||
<InputField style={styles.field}
|
||||
label={state.strings.typeDelete}
|
||||
value={state.confirm}
|
||||
autoCapitalize={'none'}
|
||||
spellCheck={false}
|
||||
onChangeText={actions.setConfirm}
|
||||
/>
|
||||
|
||||
<View style={styles.buttons}>
|
||||
{ state.confirm === state.strings.deleteKey && (
|
||||
<TouchableOpacity style={styles.dangerButton} activeOpacity={1} onPress={deleteAccount}>
|
||||
<Text style={styles.dangerButtonText}>{ state.strings.delete }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.confirm !== state.strings.deleteKey && (
|
||||
<View style={styles.disabledButton}>
|
||||
<Text style={styles.disabledButtonText}>{ state.strings.delete }</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
@ -715,35 +705,32 @@ export function Settings({ drawer }) {
|
||||
onRequestClose={state.hideBlockedContacts}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.modalBase}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideBlockedContacts}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.blockedContacts }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
<View style={styles.modalList}>
|
||||
{ state.contacts.length === 0 && (
|
||||
<View style={styles.emptyLabel}>
|
||||
<Text style={styles.emptyLabelText}>{ state.strings.noBlockedContacts }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.contacts.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.contacts}
|
||||
renderItem={BlockedContact}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.rightButton}>
|
||||
<TouchableOpacity style={styles.closeButton} activeOpacity={1} onPress={actions.hideBlockedContacts}>
|
||||
<Text style={styles.closeButtonText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideBlockedContacts}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.blockedContacts }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
<View style={styles.modalList}>
|
||||
{ state.contacts.length === 0 && (
|
||||
<View style={styles.emptyLabel}>
|
||||
<Text style={styles.emptyLabelText}>{ state.strings.noBlockedContacts }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.contacts.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.contacts}
|
||||
renderItem={BlockedContact}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.rightButton}>
|
||||
<TouchableOpacity style={styles.closeButton} activeOpacity={1} onPress={actions.hideBlockedContacts}>
|
||||
<Text style={styles.closeButtonText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -757,35 +744,32 @@ export function Settings({ drawer }) {
|
||||
onRequestClose={state.hideBlockedTopics}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.modalBase}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideBlockedTopics}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.blockedTopics }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
<View style={styles.modalList}>
|
||||
{ state.topics.length === 0 && (
|
||||
<View style={styles.emptyLabel}>
|
||||
<Text style={styles.emptyLabelText}>{ state.strings.noBlockedTopics }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.topics.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.topics}
|
||||
renderItem={BlockedTopic}
|
||||
keyExtractor={item => `${item.cardId}.${item.channelId}`}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.rightButton}>
|
||||
<TouchableOpacity style={styles.closeButton} activeOpacity={1} onPress={actions.hideBlockedTopics}>
|
||||
<Text style={styles.closeButtonText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideBlockedTopics}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.blockedTopics }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
<View style={styles.modalList}>
|
||||
{ state.topics.length === 0 && (
|
||||
<View style={styles.emptyLabel}>
|
||||
<Text style={styles.emptyLabelText}>{ state.strings.noBlockedTopics }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.topics.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.topics}
|
||||
renderItem={BlockedTopic}
|
||||
keyExtractor={item => `${item.cardId}.${item.channelId}`}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.rightButton}>
|
||||
<TouchableOpacity style={styles.closeButton} activeOpacity={1} onPress={actions.hideBlockedTopics}>
|
||||
<Text style={styles.closeButtonText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -799,35 +783,32 @@ export function Settings({ drawer }) {
|
||||
onRequestClose={actions.hideBlockedMessages}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.modalBase}>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideBlockedMessages}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.blockedMessages }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
<View style={styles.modalList}>
|
||||
{ state.messages.length === 0 && (
|
||||
<View style={styles.emptyLabel}>
|
||||
<Text style={styles.emptyLabelText}>{ state.strings.noBlockedMessages }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.messages.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.messages}
|
||||
renderItem={BlockedMessage}
|
||||
keyExtractor={item => `${item.cardId}.${item.channelId}.${item.topicId}`}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.rightButton}>
|
||||
<TouchableOpacity style={styles.closeButton} activeOpacity={1} onPress={actions.hideBlockedMessages}>
|
||||
<Text style={styles.closeButtonText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalClose}>
|
||||
<TouchableOpacity style={styles.dismissButton} activeOpacity={1} onPress={actions.hideBlockedMessages}>
|
||||
<MatIcons name="close" size={20} color={Colors.descriptionText} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.modalHeader}>{ state.strings.blockedMessages }</Text>
|
||||
<ActivityIndicator style={styles.modalBusy} animating={busy} color={Colors.primary} />
|
||||
<View style={styles.modalList}>
|
||||
{ state.messages.length === 0 && (
|
||||
<View style={styles.emptyLabel}>
|
||||
<Text style={styles.emptyLabelText}>{ state.strings.noBlockedMessages }</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.messages.length !== 0 && (
|
||||
<FlatList
|
||||
data={state.messages}
|
||||
renderItem={BlockedMessage}
|
||||
keyExtractor={item => `${item.cardId}.${item.channelId}.${item.topicId}`}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.rightButton}>
|
||||
<TouchableOpacity style={styles.closeButton} activeOpacity={1} onPress={actions.hideBlockedMessages}>
|
||||
<Text style={styles.closeButtonText}>{ state.strings.close }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
@ -130,16 +130,11 @@ export const styles = StyleSheet.create({
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
modalBase: {
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.modalBase,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { Modal, View, Text, TouchableOpacity, ActivityIndicator } from 'react-native';
|
||||
import { DisplayContext } from 'context/DisplayContext';
|
||||
import { BlurView } from "@react-native-community/blur";
|
||||
import { styles } from './Prompt.styled';
|
||||
import { Colors } from 'constants/Colors';
|
||||
|
||||
@ -41,27 +40,24 @@ export function Prompt() {
|
||||
onRequestClose={display.actions.hidePrompt}
|
||||
>
|
||||
<View style={styles.modalOverlay}>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
|
||||
<View style={styles.modalBase}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.modalHeader}>{ display.state.prompt?.title }</Text>
|
||||
<View style={display.state.prompt?.centerButtons ? styles.centerModalButtons : styles.modalButtons}>
|
||||
{ display.state.prompt?.cancel && (
|
||||
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={display.actions.hidePrompt}>
|
||||
<Text style={styles.cancelButtonText}>{ display.state.prompt?.cancel?.label }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ display.state.prompt?.ok && (
|
||||
<TouchableOpacity style={styles.okButton} activeOpacity={1} onPress={okPrompt}>
|
||||
{ !busy && (
|
||||
<Text style={styles.okButtonText}>{ display.state.prompt?.ok?.label }</Text>
|
||||
)}
|
||||
{ busy && (
|
||||
<ActivityIndicator animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.modalHeader}>{ display.state.prompt?.title }</Text>
|
||||
<View style={display.state.prompt?.centerButtons ? styles.centerModalButtons : styles.modalButtons}>
|
||||
{ display.state.prompt?.cancel && (
|
||||
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={display.actions.hidePrompt}>
|
||||
<Text style={styles.cancelButtonText}>{ display.state.prompt?.cancel?.label }</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ display.state.prompt?.ok && (
|
||||
<TouchableOpacity style={styles.okButton} activeOpacity={1} onPress={okPrompt}>
|
||||
{ !busy && (
|
||||
<Text style={styles.okButtonText}>{ display.state.prompt?.ok?.label }</Text>
|
||||
)}
|
||||
{ busy && (
|
||||
<ActivityIndicator animating={true} color={Colors.primaryButtonText} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -74,7 +70,7 @@ export function Prompt() {
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={display.actions.hideAlert}
|
||||
>
|
||||
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black">
|
||||
<View styles={styles.modalOverlay}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.modalHeader}>{ display.state.alert?.title }</Text>
|
||||
<Text style={styles.modalMessage}>{ display.state.alert?.message }</Text>
|
||||
@ -82,7 +78,7 @@ export function Prompt() {
|
||||
<Text style={styles.okButtonText}>{ display.state.alert?.ok }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</BlurView>
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
@ -5,16 +5,11 @@ export const styles = StyleSheet.create({
|
||||
modalOverlay: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
modalBase: {
|
||||
backgroundColor: Colors.modalOverlay,
|
||||
opacity: 0.8,
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.modalBase,
|
||||
|
4824
app/mobile/yarn.lock
1
fastlane/metadata/android/en-US/changelogs/2.txt
Normal file
@ -0,0 +1 @@
|
||||
* Updated fastlane description
|
1
fastlane/metadata/android/en-US/changelogs/3.txt
Normal file
@ -0,0 +1 @@
|
||||
* Updated fastlane description
|
11
fastlane/metadata/android/en-US/full_description.txt
Normal file
@ -0,0 +1,11 @@
|
||||
Notable features of Databag include:
|
||||
- Decentralized (direct communication between app and selfhosted server)
|
||||
- Federated (accounts on different nodes can communicate)
|
||||
- Public-Private key based identity (not bound to any blockchain or hosting domain)
|
||||
- End-to-End encryption (the hosting admin cannot view sealed topics, default unsealed)
|
||||
- Audio and Video Calls (nat traversal requires separate relay server)
|
||||
- Topic based threads (messages organized by topic not contacts)
|
||||
- Lightweight (server can run on a raspberry pi zero v1.3)
|
||||
- Low latency (use of websockets for push events to avoid polling)
|
||||
- Unlimited accounts per node (host for your whole family)
|
||||
- Mobile alerts for new contacts, messages, and calls (supports UnifiedPush)
|
BIN
fastlane/metadata/android/en-US/images/featureGraphic.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
fastlane/metadata/android/en-US/images/promoGraphic.png
Normal file
After Width: | Height: | Size: 106 KiB |
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
@ -0,0 +1 @@
|
||||
A federated chat client designed for privacy and selfhosting.
|
1
fastlane/metadata/android/en-US/title.txt
Normal file
@ -0,0 +1 @@
|
||||
Databag
|
1
fastlane/metadata/android/en-US/video.txt
Normal file
@ -0,0 +1 @@
|
||||
https://www.youtube.com/watch?v=81WTK3rdqGE
|