mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-17 15:48:26 +00:00
Merge branch 'dev' of https://github.com/loki-project/session-android into zombie-handling-update
This commit is contained in:
commit
365ccda113
10
.tx/config
10
.tx/config
@ -1,10 +0,0 @@
|
|||||||
[main]
|
|
||||||
host = https://www.transifex.com
|
|
||||||
lang_map = da_DK:da-rDK,he:iw,id:in,kn_IN:kn-rIN,pt_BR:pt-rBR,pt_PT:pt,qu_EC:qu-rEC,sv_SE:sv-rSE,zh_CN:zh-rCN,zh_HK:zh-rHK,zh_TW:zh-rTW
|
|
||||||
|
|
||||||
[signal-android.master]
|
|
||||||
file_filter = app/src/main/res/values-<lang>/strings.xml
|
|
||||||
source_file = app/src/main/res/values/strings.xml
|
|
||||||
source_lang = en
|
|
||||||
type = ANDROID
|
|
||||||
|
|
26
BUILDING.md
26
BUILDING.md
@ -15,11 +15,11 @@ You will need Java 8 set up on your machine.
|
|||||||
Ensure that the following packages are installed from the Android SDK manager:
|
Ensure that the following packages are installed from the Android SDK manager:
|
||||||
|
|
||||||
* Android SDK Build Tools (see buildToolsVersion in build.gradle)
|
* Android SDK Build Tools (see buildToolsVersion in build.gradle)
|
||||||
* SDK Platform (All API levels)
|
* SDK Platform (all API levels)
|
||||||
* Android Support Repository
|
* Android Support Repository
|
||||||
* Google Repository
|
* Google Repository
|
||||||
|
|
||||||
In Android studio, this can be done from the Quickstart panel, choose "Configure" then "SDK Manager". In the SDK Tools tab of the SDK Manager, make sure that the "Android Support Repository" is installed, and that the latest "Android SDK build-tools" are installed. Click "OK" to return to the Quickstart panel. You may also need to install API version 28 in the SDK platforms tab.
|
In Android studio, this can be done from the Quickstart panel. Just choose "Configure", then "SDK Manager". In the SDK Tools tab of the SDK Manager, make sure that "Android Support Repository" is installed, and that the latest "Android SDK build-tools" are installed. Click "OK" to return to the Quickstart panel. You may also need to install API version 28 in the SDK platforms tab.
|
||||||
|
|
||||||
Setting up a development environment and building from Android Studio
|
Setting up a development environment and building from Android Studio
|
||||||
------------------------------------
|
------------------------------------
|
||||||
@ -33,27 +33,7 @@ Setting up a development environment and building from Android Studio
|
|||||||
5. Default config options should be good enough.
|
5. Default config options should be good enough.
|
||||||
6. Project initialization and building should proceed.
|
6. Project initialization and building should proceed.
|
||||||
|
|
||||||
Building Session from the command line
|
|
||||||
---------------
|
|
||||||
|
|
||||||
The following steps should help you (re)build Session from the command line once all dependencies have been acquired.
|
|
||||||
|
|
||||||
1. Checkout the session-android project source with the command:
|
|
||||||
|
|
||||||
git clone https://github.com/oxen-io/session-android.git
|
|
||||||
|
|
||||||
2. Make sure you have the [Android SDK](https://developer.android.com/sdk/index.html) installed.
|
|
||||||
3. Create a local.properties file at the root of your source checkout and add an sdk.dir entry to it. For example:
|
|
||||||
|
|
||||||
sdk.dir=/Application/android-sdk-macosx
|
|
||||||
|
|
||||||
4. Execute Gradle:
|
|
||||||
|
|
||||||
./gradlew :app:build
|
|
||||||
|
|
||||||
Contributing code
|
Contributing code
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The bulk of the Session code can be found under src/org/thoughtcrime/securesms/loki on this repo and java/main/java/org/whispersystems/signalservice/loki on the session-android-service repo.
|
Code contributions should be sent via Github as pull requests, from feature branches [as explained here](https://help.github.com/articles/using-pull-requests).
|
||||||
|
|
||||||
Code contributions should be sent via github as pull requests, from feature branches [as explained here](https://help.github.com/articles/using-pull-requests).
|
|
||||||
|
34
NOTICE
34
NOTICE
@ -1,34 +0,0 @@
|
|||||||
TextSecure provides encrypted text messages for Android.
|
|
||||||
Copyright 2011 Whisper Systems
|
|
||||||
|
|
||||||
This software has the follow third party dependencies:
|
|
||||||
|
|
||||||
Bouncy Castle 1.42
|
|
||||||
http://www.bouncycastle.org/
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
ZXing
|
|
||||||
http://code.google.com/p/zxing/
|
|
||||||
Apache License 2.0
|
|
||||||
|
|
||||||
Copyright 2009 ZXing authors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
45
README.md
45
README.md
@ -10,7 +10,7 @@ Add the [F-Droid repo](https://fdroid.getsession.org/)
|
|||||||
|
|
||||||
Session integrates directly with [Oxen Service Nodes](https://docs.oxen.io/about-the-oxen-blockchain/oxen-service-nodes), which are a set of distributed, decentralized and Sybil resistant nodes. Service Nodes act as servers which store messages offline, and a set of nodes which allow for onion routing functionality obfuscating users' IP addresses. For a full understanding of how Session works, read the [Session Whitepaper](https://getsession.org/whitepaper).
|
Session integrates directly with [Oxen Service Nodes](https://docs.oxen.io/about-the-oxen-blockchain/oxen-service-nodes), which are a set of distributed, decentralized and Sybil resistant nodes. Service Nodes act as servers which store messages offline, and a set of nodes which allow for onion routing functionality obfuscating users' IP addresses. For a full understanding of how Session works, read the [Session Whitepaper](https://getsession.org/whitepaper).
|
||||||
|
|
||||||
![AndroidSession](https://i.imgur.com/0YC9TyI.png)
|
<img src="https://i.imgur.com/RSMrR1F.png" width="320" />
|
||||||
|
|
||||||
## Want to contribute? Found a bug or have a feature request?
|
## Want to contribute? Found a bug or have a feature request?
|
||||||
|
|
||||||
@ -20,12 +20,53 @@ Please search for any [existing issues](https://github.com/oxen-io/session-andro
|
|||||||
|
|
||||||
Build instructions can be found in [BUILDING.md](BUILDING.md).
|
Build instructions can be found in [BUILDING.md](BUILDING.md).
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
|
||||||
|
Want to help us translate Session into your language? You can do so at https://crowdin.com/project/session-android!
|
||||||
|
|
||||||
|
## Verifying signatures
|
||||||
|
|
||||||
|
**Step 1:**
|
||||||
|
|
||||||
|
```
|
||||||
|
wget https://raw.githubusercontent.com/oxen-io/oxen-core/master/utils/gpg_keys/KeeJef.asc
|
||||||
|
gpg --import KeeJef.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2:**
|
||||||
|
|
||||||
|
Get the signed hash for this release. `SESSION_VERSION` needs to be updated for the release you want to verify.
|
||||||
|
|
||||||
|
```
|
||||||
|
export SESSION_VERSION=1.10.4
|
||||||
|
wget https://github.com/oxen-io/session-android/releases/download/$SESSION_VERSION/signatures.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3:**
|
||||||
|
|
||||||
|
Verify the signature of the hashes of the files.
|
||||||
|
|
||||||
|
```
|
||||||
|
gpg --verify signatures.asc 2>&1 |grep "Good signature from"
|
||||||
|
```
|
||||||
|
|
||||||
|
The command above should print "`Good signature from "Kee Jefferys...`". If it does, the hashes are valid but we still have to make the sure the signed hashes matches the downloaded files.
|
||||||
|
|
||||||
|
**Step 4:**
|
||||||
|
|
||||||
|
Make sure the two commands below returns the same hash. If they do, files are valid.
|
||||||
|
|
||||||
|
```
|
||||||
|
sha256sum session-$SESSION_VERSION-universal.apk
|
||||||
|
grep universal.apk signatures.asc
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2011 Whisper Systems
|
Copyright 2011 Whisper Systems
|
||||||
|
|
||||||
Copyright 2013-2017 Open Whisper Systems
|
Copyright 2013-2017 Open Whisper Systems
|
||||||
|
|
||||||
Copyright 2019-2020 The Loki Project
|
Copyright 2019-2021 The Loki Project
|
||||||
|
|
||||||
Licensed under the GPLv3: http://www.gnu.org/licenses/gpl-3.0.html
|
Licensed under the GPLv3: http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
## How to translate Session into new languages quickly and easily
|
|
||||||
|
|
||||||
There are people all around the world who can benefit from access to Session — and that means we need to make Session available in as many languages as possible. We’ve had a number of requests from community members wanting to help out by translating Session into currently unsupported (or only partially supported) languages. If you speak multiple languages and you want to help us make Session available in another language you speak, this guide will show you how to translate Session’s iOS and Android apps quickly and easily.
|
|
||||||
|
|
||||||
### Translating Session for iOS:
|
|
||||||
|
|
||||||
Translating Session iOS into a new language is easy! You’ll need a web browser, a plaintext editor (TextEdit on macOS or Notepad on Windows will do), and a little bit of time and patience.
|
|
||||||
|
|
||||||
#### Step 1: Retrieving English strings
|
|
||||||
- Go to [Session’s iOS GitHub page](https://github.com/loki-project/session-ios)
|
|
||||||
- In the list of folders and files, click **Session**
|
|
||||||
- Click **Meta**
|
|
||||||
- Click **Translations**
|
|
||||||
- Click **en.lproj**
|
|
||||||
- Click **localizable.strings**
|
|
||||||
- Scroll down to Line #2557 (using the line numbers on the left-hand side of the text). This line should contain the text `// MARK: - Session` (note: if this line does not contain that text, use Ctrl+F, Cmd+F, or your browser’s Find on Page function to find the line which contains that text)
|
|
||||||
- Select and copy all text from that line down to the end of the file
|
|
||||||
- Open a plaintext editor (TextEdit on macOS, Notepad on Windows, or your preferred plaintext editor) and create a new file
|
|
||||||
- Paste the text you copied earlier into this blank file
|
|
||||||
|
|
||||||
#### Step 2: Translate!
|
|
||||||
This file will now have a large number of lines of code. Each line contains 2 sets of information, both in quotation marks, like this:
|
|
||||||
|
|
||||||
`"continue_2" = "Continue";`
|
|
||||||
|
|
||||||
For each line of code, translate the word or sentence to the **right** of the equals sign into the language you are translating into. Do **not** edit the text to the **left** of the equals sign.
|
|
||||||
|
|
||||||
Once you are finished translating, save the file with a filename that specifies which language you have translated the app into, and email the file to us at support@getsession.org along with information about the language you have translated the app into. Be sure to specify in your email that you have translated the iOS app (for information on translating the Android app, see below). Our developers will then take your translation and apply it to the Session iOS app. Thank you for helping make Session more accessible for everyone!
|
|
||||||
|
|
||||||
|
|
||||||
### Translating for Android:
|
|
||||||
|
|
||||||
It’s just as easy to add new translations on Session Android! Once again, you’ll need a web browser, a plaintext editor (TextEdit on macOS or Notepad on Windows will do), and a little bit of time and patience.
|
|
||||||
|
|
||||||
#### Step 1: Retrieving English strings
|
|
||||||
- Go to [Session’s Android GitHub page](https://github.com/loki-project/session-android)
|
|
||||||
- In the list of files and folders, click **res**
|
|
||||||
- Click **values** (you will need to scroll down to find this folder; make sure you click the folder named **values** and not any of the folders named **values-xx** or with other suffixes)
|
|
||||||
- Click **strings.xml**
|
|
||||||
- Scroll down to Line #1657 (using the line numbers on the left-hand side of the text). This line should contain the text `<!-- Session -->` (note: if this line does not contain that text, use Ctrl+F, Cmd+F, or your browser’s Find on Page function to find the line which contains that text)
|
|
||||||
- Select and copy all text from that line down to the end of the file
|
|
||||||
- Open a plaintext editor (TextEdit on macOS, Notepad on Windows, or your preferred plaintext editor) and create a new file
|
|
||||||
- Paste the text you copied earlier into this blank file
|
|
||||||
|
|
||||||
#### Step 2: Translate!
|
|
||||||
This file will now have a large number of lines of code. Each line will contain `<string name=”xxx”>` and `</string>` tags. To translate Session Android, translate the text between these tags. For example:
|
|
||||||
|
|
||||||
`<string name="continue_2">Continue</string>`
|
|
||||||
|
|
||||||
In this line, translate the word **Continue** into the language you are translating into. Do not translate any other text. Do **not** translate the text inside either pair of angled brackets <>.
|
|
||||||
|
|
||||||
Translate the word or sentence between each pair of `<string></string>` tags, on each line.
|
|
||||||
|
|
||||||
Once you are finished translating, save the file with a filename that specifies which language you have translated the app into, and email the file to us at support@getsession.org along with information about the language you have translated the app into. Be sure to specify in your email that you have translated the Android app (for information on translating the iOS app, see above). Our developers will then take your translation and apply it to the Session Android app. Thank you for helping make Session more accessible for everyone!
|
|
@ -143,8 +143,8 @@ dependencies {
|
|||||||
testImplementation 'org.robolectric:shadows-multidex:4.2'
|
testImplementation 'org.robolectric:shadows-multidex:4.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
def canonicalVersionCode = 169
|
def canonicalVersionCode = 174
|
||||||
def canonicalVersionName = "1.10.7"
|
def canonicalVersionName = "1.10.8"
|
||||||
|
|
||||||
def postFixSize = 10
|
def postFixSize = 10
|
||||||
def abiPostFix = ['armeabi-v7a' : 1,
|
def abiPostFix = ['armeabi-v7a' : 1,
|
||||||
|
@ -172,9 +172,6 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.loki.activities.ChatSettingsActivity"
|
android:name="org.thoughtcrime.securesms.loki.activities.ChatSettingsActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.loki.activities.LinkedDevicesActivity"
|
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.ShareActivity"
|
android:name="org.thoughtcrime.securesms.ShareActivity"
|
||||||
@ -224,24 +221,6 @@
|
|||||||
android:resource="@mipmap/ic_launcher" />
|
android:resource="@mipmap/ic_launcher" />
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:noHistory="true"
|
|
||||||
android:theme="@style/Theme.TextSecure.DayNight.NoActionBar"
|
|
||||||
android:windowSoftInputMode="stateHidden">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
|
||||||
|
|
||||||
<data
|
|
||||||
android:host="addstickers"
|
|
||||||
android:scheme="sgnl" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.conversation.ConversationActivity"
|
android:name="org.thoughtcrime.securesms.conversation.ConversationActivity"
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||||
@ -282,23 +261,11 @@
|
|||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/NoAnimation.Theme.AppCompat.Light.DarkActionBar" />
|
android:theme="@style/NoAnimation.Theme.AppCompat.Light.DarkActionBar" />
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.PassphraseCreateActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:label="@string/AndroidManifest__create_passphrase"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:theme="@style/Theme.Session.DayNight.NoActionBar"
|
|
||||||
android:windowSoftInputMode="stateUnchanged" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.PassphrasePromptActivity"
|
android:name="org.thoughtcrime.securesms.PassphrasePromptActivity"
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/Theme.Session.DayNight.NoActionBar"/>
|
android:theme="@style/Theme.Session.DayNight.NoActionBar"/>
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.PushContactSelectionActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:label="@string/AndroidManifest__select_contacts"
|
|
||||||
android:windowSoftInputMode="stateHidden" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.giph.ui.GiphyActivity"
|
android:name="org.thoughtcrime.securesms.giph.ui.GiphyActivity"
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/*
|
/* Copyright (C) 2013 Open Whisper Systems
|
||||||
* Copyright (C) 2013 Open Whisper Systems
|
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -22,38 +21,33 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||||
import androidx.multidex.MultiDexApplication;
|
import androidx.multidex.MultiDexApplication;
|
||||||
|
|
||||||
import org.conscrypt.Conscrypt;
|
import org.conscrypt.Conscrypt;
|
||||||
import org.session.libsession.avatars.AvatarHelper;
|
import org.session.libsession.avatars.AvatarHelper;
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
||||||
import org.session.libsession.messaging.file_server.FileServerAPI;
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
import org.session.libsession.messaging.mentions.MentionsManager;
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI;
|
|
||||||
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPoller;
|
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
||||||
import org.session.libsession.snode.SnodeModule;
|
import org.session.libsession.snode.SnodeModule;
|
||||||
import org.session.libsession.utilities.Address;
|
import org.session.libsession.utilities.Address;
|
||||||
import org.session.libsession.utilities.IdentityKeyUtil;
|
|
||||||
import org.session.libsession.utilities.ProfileKeyUtil;
|
|
||||||
import org.session.libsession.utilities.ProfilePictureUtilities;
|
import org.session.libsession.utilities.ProfilePictureUtilities;
|
||||||
import org.session.libsession.utilities.SSKEnvironment;
|
import org.session.libsession.utilities.SSKEnvironment;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
|
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||||
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
|
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
|
||||||
import org.session.libsignal.database.LokiAPIDatabaseProtocol;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.session.libsignal.utilities.ThreadUtils;
|
import org.session.libsignal.utilities.ThreadUtils;
|
||||||
import org.signal.aesgcmprovider.AesGcmProvider;
|
import org.signal.aesgcmprovider.AesGcmProvider;
|
||||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||||
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
|
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
|
||||||
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
|
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
|
||||||
@ -69,9 +63,10 @@ import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
|
|||||||
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
|
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
|
||||||
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
|
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
|
import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
||||||
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||||
@ -89,14 +84,12 @@ import org.webrtc.PeerConnectionFactory;
|
|||||||
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
||||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||||
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import dagger.ObjectGraph;
|
import dagger.ObjectGraph;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlinx.coroutines.Job;
|
import kotlinx.coroutines.Job;
|
||||||
@ -131,7 +124,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
// Loki
|
// Loki
|
||||||
public MessageNotifier messageNotifier = null;
|
public MessageNotifier messageNotifier = null;
|
||||||
public Poller poller = null;
|
public Poller poller = null;
|
||||||
public ClosedGroupPoller closedGroupPoller = null;
|
|
||||||
public Broadcaster broadcaster = null;
|
public Broadcaster broadcaster = null;
|
||||||
public SignalCommunicationModule communicationModule;
|
public SignalCommunicationModule communicationModule;
|
||||||
private Job firebaseInstanceIdJob;
|
private Job firebaseInstanceIdJob;
|
||||||
@ -158,32 +150,20 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
initializeDependencyInjection();
|
initializeDependencyInjection();
|
||||||
NotificationChannels.create(this);
|
NotificationChannels.create(this);
|
||||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
||||||
// Loki
|
|
||||||
// ========
|
|
||||||
AppContext.INSTANCE.configureKovenant();
|
AppContext.INSTANCE.configureKovenant();
|
||||||
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
|
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
|
||||||
broadcaster = new Broadcaster(this);
|
broadcaster = new Broadcaster(this);
|
||||||
threadNotificationHandler = new Handler(Looper.getMainLooper());
|
threadNotificationHandler = new Handler(Looper.getMainLooper());
|
||||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
|
||||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
|
||||||
MessagingModuleConfiguration.Companion.configure(this,
|
MessagingModuleConfiguration.Companion.configure(this,
|
||||||
DatabaseFactory.getStorage(this),
|
DatabaseFactory.getStorage(this),
|
||||||
DatabaseFactory.getAttachmentProvider(this));
|
DatabaseFactory.getAttachmentProvider(this));
|
||||||
SnodeModule.Companion.configure(apiDB, broadcaster);
|
SnodeModule.Companion.configure(apiDB, broadcaster);
|
||||||
if (userPublicKey != null) {
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, userDB);
|
|
||||||
}
|
|
||||||
setUpStorageAPIIfNeeded();
|
|
||||||
resubmitProfilePictureIfNeeded();
|
|
||||||
updateOpenGroupProfilePicturesIfNeeded();
|
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
registerForFCMIfNeeded(false);
|
registerForFCMIfNeeded(false);
|
||||||
}
|
}
|
||||||
// Set application UI mode (day/night theme) to the user selected one.
|
|
||||||
UiModeUtilities.setupUiModeToUserSelected(this);
|
UiModeUtilities.setupUiModeToUserSelected(this);
|
||||||
// ========
|
|
||||||
initializeExpiringMessageManager();
|
initializeExpiringMessageManager();
|
||||||
initializeTypingStatusRepository();
|
initializeTypingStatusRepository();
|
||||||
initializeTypingStatusSender();
|
initializeTypingStatusSender();
|
||||||
@ -194,6 +174,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
initializeJobManager();
|
initializeJobManager();
|
||||||
initializeWebRtc();
|
initializeWebRtc();
|
||||||
initializeBlobProvider();
|
initializeBlobProvider();
|
||||||
|
resubmitProfilePictureIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -201,13 +182,33 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
isAppVisible = true;
|
isAppVisible = true;
|
||||||
Log.i(TAG, "App is now visible.");
|
Log.i(TAG, "App is now visible.");
|
||||||
KeyCachingService.onAppForegrounded(this);
|
KeyCachingService.onAppForegrounded(this);
|
||||||
// Loki
|
|
||||||
|
boolean hasPerformedContactMigration = TextSecurePreferences.INSTANCE.hasPerformedContactMigration(this);
|
||||||
|
if (!hasPerformedContactMigration) {
|
||||||
|
TextSecurePreferences.INSTANCE.setPerformedContactMigration(this);
|
||||||
|
Set<Recipient> allContacts = ContactUtilities.getAllContacts(this);
|
||||||
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(this);
|
||||||
|
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||||
|
for (Recipient recipient : allContacts) {
|
||||||
|
if (recipient.isGroupRecipient()) { continue; }
|
||||||
|
String sessionID = recipient.getAddress().serialize();
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(sessionID);
|
||||||
|
if (contact == null) {
|
||||||
|
contact = new Contact(sessionID);
|
||||||
|
String name = userDB.getDisplayName(sessionID);
|
||||||
|
contact.setName(name);
|
||||||
|
contact.setProfilePictureURL(recipient.getProfileAvatar());
|
||||||
|
contact.setProfilePictureEncryptionKey(recipient.getProfileKey());
|
||||||
|
contact.setTrusted(true);
|
||||||
|
}
|
||||||
|
contactDB.setContact(contact);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (poller != null) {
|
if (poller != null) {
|
||||||
poller.setCaughtUp(false);
|
poller.setCaughtUp(false);
|
||||||
}
|
}
|
||||||
startPollingIfNeeded();
|
startPollingIfNeeded();
|
||||||
|
|
||||||
OpenGroupManager.INSTANCE.setAllCaughtUp(false);
|
|
||||||
OpenGroupManager.INSTANCE.startPolling();
|
OpenGroupManager.INSTANCE.startPolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,13 +218,10 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
Log.i(TAG, "App is no longer visible.");
|
Log.i(TAG, "App is no longer visible.");
|
||||||
KeyCachingService.onAppBackgrounded(this);
|
KeyCachingService.onAppBackgrounded(this);
|
||||||
messageNotifier.setVisibleThread(-1);
|
messageNotifier.setVisibleThread(-1);
|
||||||
// Loki
|
|
||||||
if (poller != null) {
|
if (poller != null) {
|
||||||
poller.stopIfNeeded();
|
poller.stopIfNeeded();
|
||||||
}
|
}
|
||||||
if (closedGroupPoller != null) {
|
ClosedGroupPollerV2.getShared().stop();
|
||||||
closedGroupPoller.stopIfNeeded();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -314,13 +312,13 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
|
|
||||||
private void initializeJobManager() {
|
private void initializeJobManager() {
|
||||||
this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
|
this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
|
||||||
.setDataSerializer(new JsonDataSerializer())
|
.setDataSerializer(new JsonDataSerializer())
|
||||||
.setJobFactories(JobManagerFactories.getJobFactories(this))
|
.setJobFactories(JobManagerFactories.getJobFactories(this))
|
||||||
.setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
|
.setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
|
||||||
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
|
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
|
||||||
.setJobStorage(new FastJobStorage(DatabaseFactory.getJobDatabase(this)))
|
.setJobStorage(new FastJobStorage(DatabaseFactory.getJobDatabase(this)))
|
||||||
.setDependencyInjector(this)
|
.setDependencyInjector(this)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeDependencyInjection() {
|
private void initializeDependencyInjection() {
|
||||||
@ -328,7 +326,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
this.objectGraph = ObjectGraph.create(communicationModule);
|
this.objectGraph = ObjectGraph.create(communicationModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initializeExpiringMessageManager() {
|
private void initializeExpiringMessageManager() {
|
||||||
this.expiringMessageManager = new ExpiringMessageManager(this);
|
this.expiringMessageManager = new ExpiringMessageManager(this);
|
||||||
}
|
}
|
||||||
@ -350,7 +347,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializePeriodicTasks() {
|
private void initializePeriodicTasks() {
|
||||||
BackgroundPollWorker.schedulePeriodic(this); // Loki
|
BackgroundPollWorker.schedulePeriodic(this);
|
||||||
|
|
||||||
if (BuildConfig.PLAY_STORE_DISABLED) {
|
if (BuildConfig.PLAY_STORE_DISABLED) {
|
||||||
UpdateApkRefreshListener.schedule(this);
|
UpdateApkRefreshListener.schedule(this);
|
||||||
@ -404,20 +401,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
|
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ProviderInitializationException extends RuntimeException {
|
private static class ProviderInitializationException extends RuntimeException { }
|
||||||
}
|
|
||||||
|
|
||||||
// region Loki
|
|
||||||
public boolean setUpStorageAPIIfNeeded() {
|
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
|
||||||
if (userPublicKey == null || !IdentityKeyUtil.hasIdentityKey(this)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
|
||||||
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
|
||||||
FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerForFCMIfNeeded(final Boolean force) {
|
public void registerForFCMIfNeeded(final Boolean force) {
|
||||||
if (firebaseInstanceIdJob != null && firebaseInstanceIdJob.isActive() && !force) return;
|
if (firebaseInstanceIdJob != null && firebaseInstanceIdJob.isActive() && !force) return;
|
||||||
@ -449,7 +433,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
poller = new Poller();
|
poller = new Poller();
|
||||||
closedGroupPoller = new ClosedGroupPoller();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startPollingIfNeeded() {
|
public void startPollingIfNeeded() {
|
||||||
@ -457,9 +440,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
if (poller != null) {
|
if (poller != null) {
|
||||||
poller.startIfNeeded();
|
poller.startIfNeeded();
|
||||||
}
|
}
|
||||||
if (closedGroupPoller != null) {
|
ClosedGroupPollerV2.getShared().start();
|
||||||
closedGroupPoller.startIfNeeded();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resubmitProfilePictureIfNeeded() {
|
private void resubmitProfilePictureIfNeeded() {
|
||||||
@ -496,19 +477,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateOpenGroupProfilePicturesIfNeeded() {
|
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
byte[] profileKey = ProfileKeyUtil.getProfileKey(this);
|
|
||||||
String url = TextSecurePreferences.getProfilePictureURL(this);
|
|
||||||
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers();
|
|
||||||
for (String server : servers) {
|
|
||||||
if (profileKey != null) {
|
|
||||||
OpenGroupAPI.setProfilePicture(server, profileKey, url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearAllData(boolean isMigratingToV2KeyPair) {
|
public void clearAllData(boolean isMigratingToV2KeyPair) {
|
||||||
String token = TextSecurePreferences.getFCMToken(this);
|
String token = TextSecurePreferences.getFCMToken(this);
|
||||||
if (token != null && !token.isEmpty()) {
|
if (token != null && !token.isEmpty()) {
|
||||||
|
@ -30,18 +30,15 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
|
|
||||||
import org.session.libsession.messaging.messages.visible.LinkPreview;
|
import org.session.libsession.messaging.messages.visible.LinkPreview;
|
||||||
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation;
|
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation;
|
||||||
import org.session.libsession.messaging.messages.visible.Quote;
|
import org.session.libsession.messaging.messages.visible.Quote;
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||||
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
|
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
|
||||||
@ -264,7 +261,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
toFrom.setText(toFromRes);
|
toFrom.setText(toFromRes);
|
||||||
long threadID = messageRecord.getThreadId();
|
long threadID = messageRecord.getThreadId();
|
||||||
OpenGroup openGroup = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadID);
|
OpenGroupV2 openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID);
|
||||||
if (openGroup != null && messageRecord.isOutgoing()) {
|
if (openGroup != null && messageRecord.isOutgoing()) {
|
||||||
toFrom.setVisibility(View.GONE);
|
toFrom.setVisibility(View.GONE);
|
||||||
separator.setVisibility(View.GONE);
|
separator.setVisibility(View.GONE);
|
||||||
|
@ -5,10 +5,9 @@ import android.text.TextUtils
|
|||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.session.libsession.database.MessageDataProvider
|
import org.session.libsession.database.MessageDataProvider
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.*
|
import org.session.libsession.messaging.sending_receiving.attachments.*
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.messaging.utilities.DotNetAPI
|
import org.session.libsession.utilities.UploadResult
|
||||||
import org.session.libsession.utilities.Util
|
import org.session.libsession.utilities.Util
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.session.libsignal.messages.SignalServiceAttachment
|
import org.session.libsignal.messages.SignalServiceAttachment
|
||||||
@ -104,11 +103,7 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
|
|||||||
return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp)
|
return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOpenGroup(threadID: Long): OpenGroup? {
|
override fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: UploadResult) {
|
||||||
return null // TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: DotNetAPI.UploadResult) {
|
|
||||||
val database = DatabaseFactory.getAttachmentDatabase(context)
|
val database = DatabaseFactory.getAttachmentDatabase(context)
|
||||||
val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return
|
val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return
|
||||||
val attachmentPointer = SignalServiceAttachmentPointer(uploadResult.id,
|
val attachmentPointer = SignalServiceAttachmentPointer(uploadResult.id,
|
||||||
|
@ -13,24 +13,21 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsession.utilities.recipients.RecipientModifiedListener;
|
import org.session.libsession.utilities.recipients.RecipientModifiedListener;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
@ -197,17 +194,20 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
|
|||||||
boolean outgoing = messageType != MESSAGE_TYPE_INCOMING;
|
boolean outgoing = messageType != MESSAGE_TYPE_INCOMING;
|
||||||
boolean isOwnNumber = Util.isOwnNumber(getContext(), author.getAddress().serialize());
|
boolean isOwnNumber = Util.isOwnNumber(getContext(), author.getAddress().serialize());
|
||||||
|
|
||||||
String quoteeDisplayName = author.toShortString();
|
String quoteeDisplayName;
|
||||||
|
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(getContext()).getOrCreateThreadIdFor(conversationRecipient);
|
|
||||||
String senderHexEncodedPublicKey = author.getAddress().serialize();
|
String senderHexEncodedPublicKey = author.getAddress().serialize();
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadID);
|
|
||||||
if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
|
if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
|
||||||
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
|
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
|
||||||
} else if (publicChat != null) {
|
|
||||||
quoteeDisplayName = DatabaseFactory.getLokiUserDatabase(getContext()).getServerDisplayName(publicChat.getId(), senderHexEncodedPublicKey);
|
|
||||||
} else {
|
} else {
|
||||||
quoteeDisplayName = DatabaseFactory.getLokiUserDatabase(getContext()).getDisplayName(senderHexEncodedPublicKey);
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(getContext());
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(senderHexEncodedPublicKey);
|
||||||
|
if (contact != null) {
|
||||||
|
Contact.ContactContext context = (this.conversationRecipient.isOpenGroupRecipient()) ? Contact.ContactContext.OPEN_GROUP : Contact.ContactContext.REGULAR;
|
||||||
|
quoteeDisplayName = contact.displayName(context);
|
||||||
|
} else {
|
||||||
|
quoteeDisplayName = senderHexEncodedPublicKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authorView.setText(isOwnNumber ? getContext().getString(R.string.QuoteView_you) : quoteeDisplayName);
|
authorView.setText(isOwnNumber ? getContext().getString(R.string.QuoteView_you) : quoteeDisplayName);
|
||||||
|
@ -62,7 +62,6 @@ import android.widget.ImageView;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -77,9 +76,7 @@ import androidx.core.view.MenuItemCompat;
|
|||||||
import androidx.lifecycle.ViewModelProviders;
|
import androidx.lifecycle.ViewModelProviders;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
@ -90,7 +87,6 @@ import org.session.libsession.messaging.messages.signal.OutgoingSecureMediaMessa
|
|||||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation;
|
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation;
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||||
@ -106,6 +102,7 @@ import org.session.libsession.utilities.recipients.RecipientModifiedListener;
|
|||||||
import org.session.libsession.utilities.ExpirationUtil;
|
import org.session.libsession.utilities.ExpirationUtil;
|
||||||
import org.session.libsession.utilities.GroupUtil;
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
|
import org.session.libsession.utilities.SSKEnvironment;
|
||||||
import org.session.libsession.utilities.ServiceUtil;
|
import org.session.libsession.utilities.ServiceUtil;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
@ -160,8 +157,6 @@ import org.thoughtcrime.securesms.loki.activities.EditClosedGroupActivity;
|
|||||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||||
import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity;
|
import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity;
|
||||||
import org.thoughtcrime.securesms.loki.api.PublicChatInfoUpdateWorker;
|
import org.thoughtcrime.securesms.loki.api.PublicChatInfoUpdateWorker;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||||
@ -193,7 +188,6 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
|
|||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.PushCharacterCalculator;
|
import org.thoughtcrime.securesms.util.PushCharacterCalculator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -204,7 +198,6 @@ import java.util.Locale;
|
|||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
@ -217,14 +210,14 @@ import network.loki.messenger.R;
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||||
implements ConversationFragment.ConversationFragmentListener,
|
implements ConversationFragment.ConversationFragmentListener,
|
||||||
AttachmentManager.AttachmentListener,
|
AttachmentManager.AttachmentListener,
|
||||||
RecipientModifiedListener,
|
RecipientModifiedListener,
|
||||||
OnKeyboardShownListener,
|
OnKeyboardShownListener,
|
||||||
InputPanel.Listener,
|
InputPanel.Listener,
|
||||||
InputPanel.MediaListener,
|
InputPanel.MediaListener,
|
||||||
ComposeText.CursorPositionChangedListener,
|
ComposeText.CursorPositionChangedListener,
|
||||||
ConversationSearchBottomBar.EventListener
|
ConversationSearchBottomBar.EventListener
|
||||||
{
|
{
|
||||||
private static final String TAG = ConversationActivity.class.getSimpleName();
|
private static final String TAG = ConversationActivity.class.getSimpleName();
|
||||||
|
|
||||||
@ -239,11 +232,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
public static final String LAST_SEEN_EXTRA = "last_seen";
|
public static final String LAST_SEEN_EXTRA = "last_seen";
|
||||||
public static final String STARTING_POSITION_EXTRA = "starting_position";
|
public static final String STARTING_POSITION_EXTRA = "starting_position";
|
||||||
|
|
||||||
// private static final int PICK_GALLERY = 1;
|
// private static final int PICK_GALLERY = 1;
|
||||||
private static final int PICK_DOCUMENT = 2;
|
private static final int PICK_DOCUMENT = 2;
|
||||||
private static final int PICK_AUDIO = 3;
|
private static final int PICK_AUDIO = 3;
|
||||||
private static final int PICK_CONTACT = 4;
|
private static final int PICK_CONTACT = 4;
|
||||||
// private static final int GET_CONTACT_DETAILS = 5;
|
// private static final int GET_CONTACT_DETAILS = 5;
|
||||||
// private static final int GROUP_EDIT = 6;
|
// private static final int GROUP_EDIT = 6;
|
||||||
private static final int TAKE_PHOTO = 7;
|
private static final int TAKE_PHOTO = 7;
|
||||||
private static final int ADD_CONTACT = 8;
|
private static final int ADD_CONTACT = 8;
|
||||||
@ -377,12 +370,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, this);
|
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, this);
|
||||||
|
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
|
||||||
OpenGroupV2 openGroupV2 = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadId);
|
OpenGroupV2 openGroupV2 = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadId);
|
||||||
if (publicChat != null) {
|
if (openGroupV2 != null) {
|
||||||
// Request open group info update and handle the successful result in #onOpenGroupInfoUpdated().
|
|
||||||
PublicChatInfoUpdateWorker.scheduleInstant(this, publicChat.getServer(), publicChat.getChannel());
|
|
||||||
} else if (openGroupV2 != null) {
|
|
||||||
PublicChatInfoUpdateWorker.scheduleInstant(this, openGroupV2.getServer(), openGroupV2.getRoom());
|
PublicChatInfoUpdateWorker.scheduleInstant(this, openGroupV2.getServer(), openGroupV2.getRoom());
|
||||||
if (openGroupV2.getRoom().equals("session") || openGroupV2.getRoom().equals("oxen")
|
if (openGroupV2.getRoom().equals("session") || openGroupV2.getRoom().equals("oxen")
|
||||||
|| openGroupV2.getRoom().equals("lokinet") || openGroupV2.getRoom().equals("crypto")) {
|
|| openGroupV2.getRoom().equals("lokinet") || openGroupV2.getRoom().equals("crypto")) {
|
||||||
@ -522,90 +511,89 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
super.onActivityResult(reqCode, resultCode, data);
|
super.onActivityResult(reqCode, resultCode, data);
|
||||||
|
|
||||||
if ((data == null && reqCode != TAKE_PHOTO && reqCode != SMS_DEFAULT) ||
|
if ((data == null && reqCode != TAKE_PHOTO && reqCode != SMS_DEFAULT) ||
|
||||||
(resultCode != RESULT_OK && reqCode != SMS_DEFAULT))
|
(resultCode != RESULT_OK && reqCode != SMS_DEFAULT))
|
||||||
{
|
{
|
||||||
updateLinkPreviewState();
|
updateLinkPreviewState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (reqCode) {
|
switch (reqCode) {
|
||||||
case PICK_DOCUMENT:
|
case PICK_DOCUMENT:
|
||||||
setMedia(data.getData(), MediaType.DOCUMENT);
|
setMedia(data.getData(), MediaType.DOCUMENT);
|
||||||
break;
|
break;
|
||||||
case PICK_AUDIO:
|
case PICK_AUDIO:
|
||||||
setMedia(data.getData(), MediaType.AUDIO);
|
setMedia(data.getData(), MediaType.AUDIO);
|
||||||
break;
|
break;
|
||||||
case TAKE_PHOTO:
|
case TAKE_PHOTO:
|
||||||
if (attachmentManager.getCaptureUri() != null) {
|
if (attachmentManager.getCaptureUri() != null) {
|
||||||
setMedia(attachmentManager.getCaptureUri(), MediaType.IMAGE);
|
setMedia(attachmentManager.getCaptureUri(), MediaType.IMAGE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ADD_CONTACT:
|
case ADD_CONTACT:
|
||||||
recipient = Recipient.from(this, recipient.getAddress(), true);
|
recipient = Recipient.from(this, recipient.getAddress(), true);
|
||||||
recipient.addListener(this);
|
recipient.addListener(this);
|
||||||
fragment.reloadList();
|
fragment.reloadList();
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
case PICK_LOCATION:
|
case PICK_LOCATION:
|
||||||
SignalPlace place = new SignalPlace(PlacePicker.getPlace(data, this));
|
SignalPlace place = new SignalPlace(PlacePicker.getPlace(data, this));
|
||||||
attachmentManager.setLocation(place, getCurrentMediaConstraints());
|
attachmentManager.setLocation(place, getCurrentMediaConstraints());
|
||||||
break;
|
break;
|
||||||
*/
|
*/
|
||||||
case PICK_GIF:
|
case PICK_GIF:
|
||||||
setMedia(data.getData(),
|
setMedia(data.getData(),
|
||||||
MediaType.GIF,
|
MediaType.GIF,
|
||||||
data.getIntExtra(GiphyActivity.EXTRA_WIDTH, 0),
|
data.getIntExtra(GiphyActivity.EXTRA_WIDTH, 0),
|
||||||
data.getIntExtra(GiphyActivity.EXTRA_HEIGHT, 0));
|
data.getIntExtra(GiphyActivity.EXTRA_HEIGHT, 0));
|
||||||
break;
|
break;
|
||||||
case SMS_DEFAULT:
|
case SMS_DEFAULT:
|
||||||
initializeSecurity(true, isDefaultSms);
|
initializeSecurity(true, isDefaultSms);
|
||||||
break;
|
break;
|
||||||
case MEDIA_SENDER:
|
case MEDIA_SENDER:
|
||||||
long expiresIn = recipient.getExpireMessages() * 1000L;
|
long expiresIn = recipient.getExpireMessages() * 1000L;
|
||||||
int subscriptionId = -1;
|
int subscriptionId = -1;
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
String message = data.getStringExtra(MediaSendActivity.EXTRA_MESSAGE);
|
String message = data.getStringExtra(MediaSendActivity.EXTRA_MESSAGE);
|
||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
|
|
||||||
List<Media> mediaList = data.getParcelableArrayListExtra(MediaSendActivity.EXTRA_MEDIA);
|
List<Media> mediaList = data.getParcelableArrayListExtra(MediaSendActivity.EXTRA_MEDIA);
|
||||||
|
|
||||||
for (Media mediaItem : mediaList) {
|
for (Media mediaItem : mediaList) {
|
||||||
if (MediaUtil.isVideoType(mediaItem.getMimeType())) {
|
if (MediaUtil.isVideoType(mediaItem.getMimeType())) {
|
||||||
slideDeck.addSlide(new VideoSlide(this, mediaItem.getUri(), 0, mediaItem.getCaption().orNull()));
|
slideDeck.addSlide(new VideoSlide(this, mediaItem.getUri(), 0, mediaItem.getCaption().orNull()));
|
||||||
} else if (MediaUtil.isGif(mediaItem.getMimeType())) {
|
} else if (MediaUtil.isGif(mediaItem.getMimeType())) {
|
||||||
slideDeck.addSlide(new GifSlide(this, mediaItem.getUri(), 0, mediaItem.getWidth(), mediaItem.getHeight(), mediaItem.getCaption().orNull()));
|
slideDeck.addSlide(new GifSlide(this, mediaItem.getUri(), 0, mediaItem.getWidth(), mediaItem.getHeight(), mediaItem.getCaption().orNull()));
|
||||||
} else if (MediaUtil.isImageType(mediaItem.getMimeType())) {
|
} else if (MediaUtil.isImageType(mediaItem.getMimeType())) {
|
||||||
slideDeck.addSlide(new ImageSlide(this, mediaItem.getUri(), 0, mediaItem.getWidth(), mediaItem.getHeight(), mediaItem.getCaption().orNull()));
|
slideDeck.addSlide(new ImageSlide(this, mediaItem.getUri(), 0, mediaItem.getWidth(), mediaItem.getHeight(), mediaItem.getCaption().orNull()));
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Asked to send an unexpected mimeType: '" + mediaItem.getMimeType() + "'. Skipping.");
|
Log.w(TAG, "Asked to send an unexpected mimeType: '" + mediaItem.getMimeType() + "'. Skipping.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final Context context = ConversationActivity.this.getApplicationContext();
|
final Context context = ConversationActivity.this.getApplicationContext();
|
||||||
|
|
||||||
sendMediaMessage(message,
|
sendMediaMessage(message,
|
||||||
slideDeck,
|
slideDeck,
|
||||||
inputPanel.getQuote().orNull(),
|
inputPanel.getQuote().orNull(),
|
||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
initiating).addListener(new AssertedSuccessListener<Void>() {
|
initiating).addListener(new AssertedSuccessListener<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void result) {
|
public void onSuccess(Void result) {
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||||
Stream.of(slideDeck.getSlides())
|
Stream.of(slideDeck.getSlides())
|
||||||
.map(Slide::getUri)
|
.map(Slide::getUri)
|
||||||
.withoutNulls()
|
.withoutNulls()
|
||||||
.filter(BlobProvider::isAuthority)
|
.filter(BlobProvider::isAuthority)
|
||||||
.forEach(uri -> BlobProvider.getInstance().delete(context, uri));
|
.forEach(uri -> BlobProvider.getInstance().delete(context, uri));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
break;
|
case INVITE_CONTACTS:
|
||||||
case INVITE_CONTACTS:
|
if (data.getExtras() == null || !data.hasExtra(SelectContactsActivity.Companion.getSelectedContactsKey())) return;
|
||||||
if (data.getExtras() == null || !data.hasExtra(SelectContactsActivity.Companion.getSelectedContactsKey())) return;
|
String[] selectedContacts = data.getExtras().getStringArray(SelectContactsActivity.Companion.getSelectedContactsKey());
|
||||||
String[] selectedContacts = data.getExtras().getStringArray(SelectContactsActivity.Companion.getSelectedContactsKey());
|
sendOpenGroupInvitations(selectedContacts);
|
||||||
sendOpenGroupInvitations(selectedContacts);
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,14 +673,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if (isSingleConversation() && getRecipient().getContactUri() == null) {
|
if (isSingleConversation() && getRecipient().getContactUri() == null) {
|
||||||
inflater.inflate(R.menu.conversation_add_to_contacts, menu);
|
inflater.inflate(R.menu.conversation_add_to_contacts, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (recipient != null && recipient.isLocalNumber()) {
|
if (recipient != null && recipient.isLocalNumber()) {
|
||||||
if (isSecureText) menu.findItem(R.id.menu_call_secure).setVisible(false);
|
if (isSecureText) menu.findItem(R.id.menu_call_secure).setVisible(false);
|
||||||
else menu.findItem(R.id.menu_call_insecure).setVisible(false);
|
else menu.findItem(R.id.menu_call_insecure).setVisible(false);
|
||||||
|
|
||||||
MenuItem muteItem = menu.findItem(R.id.menu_mute_notifications);
|
MenuItem muteItem = menu.findItem(R.id.menu_mute_notifications);
|
||||||
|
|
||||||
if (muteItem != null) {
|
if (muteItem != null) {
|
||||||
muteItem.setVisible(false);
|
muteItem.setVisible(false);
|
||||||
}
|
}
|
||||||
@ -760,26 +744,26 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
// case R.id.menu_call_secure: handleDial(getRecipient(), true); return true;
|
// case R.id.menu_call_secure: handleDial(getRecipient(), true); return true;
|
||||||
// case R.id.menu_call_insecure: handleDial(getRecipient(), false); return true;
|
// case R.id.menu_call_insecure: handleDial(getRecipient(), false); return true;
|
||||||
case R.id.menu_unblock: handleUnblock(); return true;
|
case R.id.menu_unblock: handleUnblock(); return true;
|
||||||
case R.id.menu_block: handleBlock(); return true;
|
case R.id.menu_block: handleBlock(); return true;
|
||||||
case R.id.menu_copy_session_id: handleCopySessionID(); return true;
|
case R.id.menu_copy_session_id: handleCopySessionID(); return true;
|
||||||
case R.id.menu_view_media: handleViewMedia(); return true;
|
case R.id.menu_view_media: handleViewMedia(); return true;
|
||||||
case R.id.menu_add_shortcut: handleAddShortcut(); return true;
|
case R.id.menu_add_shortcut: handleAddShortcut(); return true;
|
||||||
case R.id.menu_search: handleSearch(); return true;
|
case R.id.menu_search: handleSearch(); return true;
|
||||||
// case R.id.menu_add_to_contacts: handleAddToContacts(); return true;
|
// case R.id.menu_add_to_contacts: handleAddToContacts(); return true;
|
||||||
// case R.id.menu_reset_secure_session: handleResetSecureSession(); return true;
|
// case R.id.menu_reset_secure_session: handleResetSecureSession(); return true;
|
||||||
// case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
|
// case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
|
||||||
case R.id.menu_distribution_broadcast: handleDistributionBroadcastEnabled(item); return true;
|
case R.id.menu_distribution_broadcast: handleDistributionBroadcastEnabled(item); return true;
|
||||||
case R.id.menu_distribution_conversation: handleDistributionConversationEnabled(item); return true;
|
case R.id.menu_distribution_conversation: handleDistributionConversationEnabled(item); return true;
|
||||||
case R.id.menu_edit_group: handleEditPushGroup(); return true;
|
case R.id.menu_edit_group: handleEditPushGroup(); return true;
|
||||||
case R.id.menu_leave: handleLeavePushGroup(); return true;
|
case R.id.menu_leave: handleLeavePushGroup(); return true;
|
||||||
case R.id.menu_mute_notifications: handleMuteNotifications(); return true;
|
case R.id.menu_mute_notifications: handleMuteNotifications(); return true;
|
||||||
case R.id.menu_unmute_notifications: handleUnmuteNotifications(); return true;
|
case R.id.menu_unmute_notifications: handleUnmuteNotifications(); return true;
|
||||||
// case R.id.menu_conversation_settings: handleConversationSettings(); return true;
|
// case R.id.menu_conversation_settings: handleConversationSettings(); return true;
|
||||||
case R.id.menu_expiring_messages_off:
|
case R.id.menu_expiring_messages_off:
|
||||||
case R.id.menu_expiring_messages: handleSelectMessageExpiration(); return true;
|
case R.id.menu_expiring_messages: handleSelectMessageExpiration(); return true;
|
||||||
case R.id.menu_invite_to_open_group: handleInviteToOpenGroup(); return true;
|
case R.id.menu_invite_to_open_group: handleInviteToOpenGroup(); return true;
|
||||||
case android.R.id.home: handleReturnToConversationList(); return true;
|
case android.R.id.home: handleReturnToConversationList(); return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -850,7 +834,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||||
.setMuted(recipient, until);
|
.setMuted(recipient, until);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -865,7 +849,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||||
.setMuted(recipient, 0);
|
.setMuted(recipient, 0);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -877,20 +861,20 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
int bodyRes = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact;
|
int bodyRes = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact;
|
||||||
|
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(titleRes)
|
.setTitle(titleRes)
|
||||||
.setMessage(bodyRes)
|
.setMessage(bodyRes)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
|
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||||
.setBlocked(recipient, false);
|
.setBlocked(recipient, false);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
@ -960,7 +944,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
if (icon == null) {
|
if (icon == null) {
|
||||||
icon = IconCompat.createWithResource(context, recipient.isGroupRecipient() ? R.mipmap.ic_group_shortcut
|
icon = IconCompat.createWithResource(context, recipient.isGroupRecipient() ? R.mipmap.ic_group_shortcut
|
||||||
: R.mipmap.ic_person_shortcut);
|
: R.mipmap.ic_person_shortcut);
|
||||||
}
|
}
|
||||||
|
|
||||||
return icon;
|
return icon;
|
||||||
@ -970,14 +954,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
protected void onPostExecute(IconCompat icon) {
|
protected void onPostExecute(IconCompat icon) {
|
||||||
Context context = getApplicationContext();
|
Context context = getApplicationContext();
|
||||||
String name = Optional.fromNullable(recipient.getName())
|
String name = Optional.fromNullable(recipient.getName())
|
||||||
.or(Optional.fromNullable(recipient.getProfileName()))
|
.or(Optional.fromNullable(recipient.getProfileName()))
|
||||||
.or(recipient.toShortString());
|
.or(recipient.toShortString());
|
||||||
|
|
||||||
ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(context, recipient.getAddress().serialize() + '-' + System.currentTimeMillis())
|
ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(context, recipient.getAddress().serialize() + '-' + System.currentTimeMillis())
|
||||||
.setShortLabel(name)
|
.setShortLabel(name)
|
||||||
.setIcon(icon)
|
.setIcon(icon)
|
||||||
.setIntent(ShortcutLauncherActivity.createIntent(context, recipient.getAddress()))
|
.setIntent(ShortcutLauncherActivity.createIntent(context, recipient.getAddress()))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (ShortcutManagerCompat.requestPinShortcut(context, shortcutInfo, null)) {
|
if (ShortcutManagerCompat.requestPinShortcut(context, shortcutInfo, null)) {
|
||||||
Toast.makeText(context, getString(R.string.ConversationActivity_added_to_home_screen), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, getString(R.string.ConversationActivity_added_to_home_screen), Toast.LENGTH_LONG).show();
|
||||||
@ -993,7 +977,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
private void handleLeavePushGroup() {
|
private void handleLeavePushGroup() {
|
||||||
if (getRecipient() == null) {
|
if (getRecipient() == null) {
|
||||||
Toast.makeText(this, getString(R.string.ConversationActivity_invalid_recipient),
|
Toast.makeText(this, getString(R.string.ConversationActivity_invalid_recipient),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1061,7 +1045,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
||||||
.setDistributionType(threadId, DistributionTypes.BROADCAST);
|
.setDistributionType(threadId, DistributionTypes.BROADCAST);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
@ -1077,7 +1061,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
||||||
.setDistributionType(threadId, DistributionTypes.CONVERSATION);
|
.setDistributionType(threadId, DistributionTypes.CONVERSATION);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
@ -1109,7 +1093,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
/* Loki - We don't support SMS
|
/* Loki - We don't support SMS
|
||||||
if (!isSecureText && !isPushGroupConversation()) sendButton.disableTransport(Type.TEXTSECURE);
|
if (!isSecureText && !isPushGroupConversation()) sendButton.disableTransport(Type.TEXTSECURE);
|
||||||
if (recipient.isPushGroupRecipient()) sendButton.disableTransport(Type.SMS);
|
if (recipient.isPushGroupRecipient()) sendButton.disableTransport(Type.SMS);
|
||||||
|
|
||||||
if (!recipient.isPushGroupRecipient() && recipient.isForceSmsSelection()) {
|
if (!recipient.isPushGroupRecipient() && recipient.isForceSmsSelection()) {
|
||||||
sendButton.setDefaultTransport(Type.SMS);
|
sendButton.setDefaultTransport(Type.SMS);
|
||||||
} else {
|
} else {
|
||||||
@ -1419,13 +1402,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onOpenGroupInfoUpdated(OpenGroupUtilities.GroupInfoUpdatedEvent event) {
|
public void onOpenGroupInfoUpdated(OpenGroupUtilities.GroupInfoUpdatedEvent event) {
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
|
||||||
OpenGroupV2 openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadId);
|
OpenGroupV2 openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadId);
|
||||||
if (publicChat != null &&
|
|
||||||
publicChat.getChannel() == event.getChannel() &&
|
|
||||||
publicChat.getServer().equals(event.getUrl())) {
|
|
||||||
this.updateSubtitleTextView();
|
|
||||||
}
|
|
||||||
if (openGroup != null &&
|
if (openGroup != null &&
|
||||||
openGroup.getRoom().equals(event.getRoom()) &&
|
openGroup.getRoom().equals(event.getRoom()) &&
|
||||||
openGroup.getServer().equals(event.getUrl())) {
|
openGroup.getServer().equals(event.getUrl())) {
|
||||||
@ -1440,35 +1417,35 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
Log.i(TAG, "Selected: " + type);
|
Log.i(TAG, "Selected: " + type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case AttachmentTypeSelector.ADD_GALLERY:
|
case AttachmentTypeSelector.ADD_GALLERY:
|
||||||
AttachmentManager.selectGallery(this, MEDIA_SENDER, recipient, composeText.getTextTrimmed()); break;
|
AttachmentManager.selectGallery(this, MEDIA_SENDER, recipient, composeText.getTextTrimmed()); break;
|
||||||
case AttachmentTypeSelector.ADD_DOCUMENT:
|
case AttachmentTypeSelector.ADD_DOCUMENT:
|
||||||
AttachmentManager.selectDocument(this, PICK_DOCUMENT); break;
|
AttachmentManager.selectDocument(this, PICK_DOCUMENT); break;
|
||||||
case AttachmentTypeSelector.ADD_SOUND:
|
case AttachmentTypeSelector.ADD_SOUND:
|
||||||
AttachmentManager.selectAudio(this, PICK_AUDIO); break;
|
AttachmentManager.selectAudio(this, PICK_AUDIO); break;
|
||||||
case AttachmentTypeSelector.ADD_CONTACT_INFO:
|
case AttachmentTypeSelector.ADD_CONTACT_INFO:
|
||||||
AttachmentManager.selectContactInfo(this, PICK_CONTACT); break;
|
AttachmentManager.selectContactInfo(this, PICK_CONTACT); break;
|
||||||
case AttachmentTypeSelector.ADD_LOCATION:
|
case AttachmentTypeSelector.ADD_LOCATION:
|
||||||
AttachmentManager.selectLocation(this, PICK_LOCATION); break;
|
AttachmentManager.selectLocation(this, PICK_LOCATION); break;
|
||||||
case AttachmentTypeSelector.TAKE_PHOTO:
|
case AttachmentTypeSelector.TAKE_PHOTO:
|
||||||
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
|
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
|
||||||
case AttachmentTypeSelector.ADD_GIF:
|
case AttachmentTypeSelector.ADD_GIF:
|
||||||
boolean hasSeenGIFMetaDataWarning = TextSecurePreferences.hasSeenGIFMetaDataWarning(this);
|
boolean hasSeenGIFMetaDataWarning = TextSecurePreferences.hasSeenGIFMetaDataWarning(this);
|
||||||
if (!hasSeenGIFMetaDataWarning) {
|
if (!hasSeenGIFMetaDataWarning) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
builder.setTitle("Search GIFs?");
|
builder.setTitle("Search GIFs?");
|
||||||
builder.setMessage("You will not have full metadata protection when sending GIFs.");
|
builder.setMessage("You will not have full metadata protection when sending GIFs.");
|
||||||
builder.setPositiveButton("OK", (dialog, which) -> {
|
builder.setPositiveButton("OK", (dialog, which) -> {
|
||||||
|
AttachmentManager.selectGif(this, PICK_GIF);
|
||||||
|
dialog.dismiss();
|
||||||
|
});
|
||||||
|
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
|
||||||
|
builder.create().show();
|
||||||
|
TextSecurePreferences.setHasSeenGIFMetaDataWarning(this);
|
||||||
|
} else {
|
||||||
AttachmentManager.selectGif(this, PICK_GIF);
|
AttachmentManager.selectGif(this, PICK_GIF);
|
||||||
dialog.dismiss();
|
}
|
||||||
});
|
break;
|
||||||
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
|
|
||||||
builder.create().show();
|
|
||||||
TextSecurePreferences.setHasSeenGIFMetaDataWarning(this);
|
|
||||||
} else {
|
|
||||||
AttachmentManager.selectGif(this, PICK_GIF);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1563,8 +1540,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
draftDatabase.insertDrafts(threadId, drafts);
|
draftDatabase.insertDrafts(threadId, drafts);
|
||||||
threadDatabase.updateSnippet(threadId, drafts.getSnippet(ConversationActivity.this),
|
threadDatabase.updateSnippet(threadId, drafts.getSnippet(ConversationActivity.this),
|
||||||
drafts.getUriSnippet(),
|
drafts.getUriSnippet(),
|
||||||
System.currentTimeMillis(), Types.BASE_DRAFT_TYPE, true);
|
System.currentTimeMillis(), Types.BASE_DRAFT_TYPE, true);
|
||||||
} else if (threadId > 0) {
|
} else if (threadId > 0) {
|
||||||
threadDatabase.update(threadId, false);
|
threadDatabase.update(threadId, false);
|
||||||
}
|
}
|
||||||
@ -1667,10 +1644,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HHmmss", Locale.US).format(new Date());
|
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HHmmss", Locale.US).format(new Date());
|
||||||
String filename = String.format("signal-%s.txt", timestamp);
|
String filename = String.format("signal-%s.txt", timestamp);
|
||||||
Uri textUri = BlobProvider.getInstance()
|
Uri textUri = BlobProvider.getInstance()
|
||||||
.forData(textData)
|
.forData(textData)
|
||||||
.withMimeType(MediaTypes.LONG_TEXT)
|
.withMimeType(MediaTypes.LONG_TEXT)
|
||||||
.withFileName(filename)
|
.withFileName(filename)
|
||||||
.createForSingleSessionInMemory();
|
.createForSingleSessionInMemory();
|
||||||
|
|
||||||
textSlide = Optional.of(new TextSlide(this, textUri, filename, textData.length));
|
textSlide = Optional.of(new TextSlide(this, textUri, filename, textData.length));
|
||||||
}
|
}
|
||||||
@ -1748,10 +1725,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
boolean needsSplit = message.length() > characterCalculator.calculateCharacters(message).maxPrimaryMessageSize;
|
boolean needsSplit = message.length() > characterCalculator.calculateCharacters(message).maxPrimaryMessageSize;
|
||||||
boolean isMediaMessage = attachmentManager.isAttachmentPresent() ||
|
boolean isMediaMessage = attachmentManager.isAttachmentPresent() ||
|
||||||
// recipient.isGroupRecipient() ||
|
// recipient.isGroupRecipient() ||
|
||||||
inputPanel.getQuote().isPresent() ||
|
inputPanel.getQuote().isPresent() ||
|
||||||
linkPreviewViewModel.hasLinkPreview() ||
|
linkPreviewViewModel.hasLinkPreview() ||
|
||||||
LinkPreviewUtil.isValidMediaUrl(message) || // Loki - Send GIFs as media messages
|
LinkPreviewUtil.isValidMediaUrl(message) || // Loki - Send GIFs as media messages
|
||||||
needsSplit;
|
needsSplit;
|
||||||
|
|
||||||
if (isMediaMessage) {
|
if (isMediaMessage) {
|
||||||
sendMediaMessage(initiating);
|
sendMediaMessage(initiating);
|
||||||
@ -1772,7 +1749,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendMediaMessage(boolean initiating)
|
private void sendMediaMessage(boolean initiating)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
Log.i(TAG, "Sending media message...");
|
Log.i(TAG, "Sending media message...");
|
||||||
sendMediaMessage(getMessage(), attachmentManager.buildSlideDeck(), inputPanel.getQuote().orNull(), linkPreviewViewModel.getActiveLinkPreview(), initiating);
|
sendMediaMessage(getMessage(), attachmentManager.buildSlideDeck(), inputPanel.getQuote().orNull(), linkPreviewViewModel.getActiveLinkPreview(), initiating);
|
||||||
@ -1832,7 +1809,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendTextMessage(final boolean initiating)
|
private void sendTextMessage(final boolean initiating)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
final Context context = getApplicationContext();
|
final Context context = getApplicationContext();
|
||||||
final String messageBody = getMessage();
|
final String messageBody = getMessage();
|
||||||
@ -1910,10 +1887,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onRecorderPermissionRequired() {
|
public void onRecorderPermissionRequired() {
|
||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(Manifest.permission.RECORD_AUDIO)
|
.request(Manifest.permission.RECORD_AUDIO)
|
||||||
.withRationaleDialog(getString(R.string.ConversationActivity_to_send_audio_messages_allow_signal_access_to_your_microphone), R.drawable.ic_baseline_mic_48)
|
.withRationaleDialog(getString(R.string.ConversationActivity_to_send_audio_messages_allow_signal_access_to_your_microphone), R.drawable.ic_baseline_mic_48)
|
||||||
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_requires_the_microphone_permission_in_order_to_send_audio_messages))
|
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_requires_the_microphone_permission_in_order_to_send_audio_messages))
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2072,16 +2049,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Permissions.with(ConversationActivity.this)
|
Permissions.with(ConversationActivity.this)
|
||||||
.request(Manifest.permission.CAMERA)
|
.request(Manifest.permission.CAMERA)
|
||||||
.withRationaleDialog(getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.ic_baseline_photo_camera_48)
|
.withRationaleDialog(getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.ic_baseline_photo_camera_48)
|
||||||
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
|
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
|
||||||
.onAllGranted(() -> {
|
.onAllGranted(() -> {
|
||||||
composeText.clearFocus();
|
composeText.clearFocus();
|
||||||
startActivityForResult(MediaSendActivity.buildCameraIntent(ConversationActivity.this, recipient), MEDIA_SENDER);
|
startActivityForResult(MediaSendActivity.buildCameraIntent(ConversationActivity.this, recipient), MEDIA_SENDER);
|
||||||
overridePendingTransition(R.anim.camera_slide_from_bottom, R.anim.stationary);
|
overridePendingTransition(R.anim.camera_slide_from_bottom, R.anim.stationary);
|
||||||
})
|
})
|
||||||
.onAnyDenied(() -> Toast.makeText(ConversationActivity.this, R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show())
|
.onAnyDenied(() -> Toast.makeText(ConversationActivity.this, R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show())
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2191,7 +2168,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
if (text.length() > 0) {
|
if (text.length() > 0) {
|
||||||
if (currentMentionStartIndex > text.length()) {
|
if (currentMentionStartIndex > text.length()) {
|
||||||
resetMentions(); // Should never occur
|
resetMentions(); // Should never occur
|
||||||
}
|
}
|
||||||
int lastCharacterIndex = text.length() - 1;
|
int lastCharacterIndex = text.length() - 1;
|
||||||
char lastCharacter = text.charAt(lastCharacterIndex);
|
char lastCharacter = text.charAt(lastCharacterIndex);
|
||||||
@ -2199,11 +2176,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if (lastCharacterIndex > 0) {
|
if (lastCharacterIndex > 0) {
|
||||||
secondToLastCharacter = text.charAt(lastCharacterIndex - 1);
|
secondToLastCharacter = text.charAt(lastCharacterIndex - 1);
|
||||||
}
|
}
|
||||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(ConversationActivity.this);
|
|
||||||
LokiThreadDatabase threadDatabase = DatabaseFactory.getLokiThreadDatabase(ConversationActivity.this);
|
|
||||||
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(ConversationActivity.this);
|
|
||||||
if (lastCharacter == '@' && Character.isWhitespace(secondToLastCharacter)) {
|
if (lastCharacter == '@' && Character.isWhitespace(secondToLastCharacter)) {
|
||||||
List<Mention> mentionCandidates = MentionsManager.shared.getMentionCandidates("", threadId);
|
List<Mention> mentionCandidates = MentionsManager.INSTANCE.getMentionCandidates("", threadId, recipient.isOpenGroupRecipient());
|
||||||
currentMentionStartIndex = lastCharacterIndex;
|
currentMentionStartIndex = lastCharacterIndex;
|
||||||
mentionCandidateSelectionViewContainer.setVisibility(View.VISIBLE);
|
mentionCandidateSelectionViewContainer.setVisibility(View.VISIBLE);
|
||||||
mentionCandidateSelectionView.show(mentionCandidates, threadId);
|
mentionCandidateSelectionView.show(mentionCandidates, threadId);
|
||||||
@ -2214,7 +2188,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
} else {
|
} else {
|
||||||
if (currentMentionStartIndex != -1) {
|
if (currentMentionStartIndex != -1) {
|
||||||
String query = text.substring(currentMentionStartIndex + 1); // + 1 to get rid of the @
|
String query = text.substring(currentMentionStartIndex + 1); // + 1 to get rid of the @
|
||||||
List<Mention> mentionCandidates = MentionsManager.shared.getMentionCandidates(query, threadId);
|
List<Mention> mentionCandidates = MentionsManager.INSTANCE.getMentionCandidates(query, threadId, recipient.isOpenGroupRecipient());
|
||||||
mentionCandidateSelectionViewContainer.setVisibility(View.VISIBLE);
|
mentionCandidateSelectionViewContainer.setVisibility(View.VISIBLE);
|
||||||
mentionCandidateSelectionView.show(mentionCandidates, threadId);
|
mentionCandidateSelectionView.show(mentionCandidates, threadId);
|
||||||
}
|
}
|
||||||
@ -2258,12 +2232,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
inputPanel.setQuote(GlideApp.with(this),
|
inputPanel.setQuote(GlideApp.with(this),
|
||||||
messageRecord.getDateSent(),
|
messageRecord.getDateSent(),
|
||||||
author,
|
author,
|
||||||
body,
|
body,
|
||||||
slideDeck,
|
slideDeck,
|
||||||
recipient,
|
recipient,
|
||||||
threadId);
|
threadId);
|
||||||
|
|
||||||
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
|
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
|
||||||
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
||||||
@ -2274,26 +2248,26 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
inputPanel.setQuote(GlideApp.with(this),
|
inputPanel.setQuote(GlideApp.with(this),
|
||||||
messageRecord.getDateSent(),
|
messageRecord.getDateSent(),
|
||||||
author,
|
author,
|
||||||
messageRecord.getBody(),
|
messageRecord.getBody(),
|
||||||
slideDeck,
|
slideDeck,
|
||||||
recipient,
|
recipient,
|
||||||
threadId);
|
threadId);
|
||||||
} else {
|
} else {
|
||||||
inputPanel.setQuote(GlideApp.with(this),
|
inputPanel.setQuote(GlideApp.with(this),
|
||||||
messageRecord.getDateSent(),
|
messageRecord.getDateSent(),
|
||||||
author,
|
author,
|
||||||
messageRecord.getBody(),
|
messageRecord.getBody(),
|
||||||
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
|
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
|
||||||
recipient,
|
recipient,
|
||||||
threadId);
|
threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageActionToolbarOpened() {
|
public void onMessageActionToolbarOpened() {
|
||||||
searchViewItem.collapseActionView();
|
searchViewItem.collapseActionView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2355,12 +2329,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
private void updateTitleTextView(Recipient recipient) {
|
private void updateTitleTextView(Recipient recipient) {
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
if (recipient == null) {
|
if (recipient == null) {
|
||||||
titleTextView.setText("Compose");
|
titleTextView.setText(R.string.ConversationActivity_compose);
|
||||||
} else if (recipient.getAddress().toString().toLowerCase().equals(userPublicKey)) {
|
} else if (recipient.getAddress().toString().toLowerCase().equals(userPublicKey)) {
|
||||||
titleTextView.setText(getResources().getString(R.string.note_to_self));
|
titleTextView.setText(R.string.note_to_self);
|
||||||
} else {
|
} else {
|
||||||
boolean hasName = (recipient.getName() != null && !recipient.getName().isEmpty());
|
String displayName = recipient.getName(); // Uses the Contact API internally
|
||||||
titleTextView.setText(hasName ? recipient.getName() : recipient.getAddress().toString());
|
boolean hasName = (displayName != null);
|
||||||
|
titleTextView.setText(hasName ? displayName : recipient.getAddress().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2378,18 +2353,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
subtitleTextView.setVisibility(View.VISIBLE);
|
subtitleTextView.setVisibility(View.VISIBLE);
|
||||||
if (recipient.isMuted()) {
|
if (recipient.isMuted()) {
|
||||||
muteIndicatorImageView.setVisibility(View.VISIBLE);
|
muteIndicatorImageView.setVisibility(View.VISIBLE);
|
||||||
subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()));
|
subtitleTextView.setText(getString(R.string.ConversationActivity_muted_until_date,DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault())));
|
||||||
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
|
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
|
||||||
OpenGroupV2 openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadId);
|
OpenGroupV2 openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadId);
|
||||||
if (publicChat != null) {
|
if (openGroup != null) {
|
||||||
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer());
|
|
||||||
if (userCount == null) { userCount = 0; }
|
|
||||||
subtitleTextView.setText(userCount + " members");
|
|
||||||
} else if (openGroup != null) {
|
|
||||||
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(openGroup.getRoom(),openGroup.getServer());
|
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(openGroup.getRoom(),openGroup.getServer());
|
||||||
if (userCount == null) { userCount = 0; }
|
if (userCount == null) { userCount = 0; }
|
||||||
subtitleTextView.setText(userCount + " members");
|
subtitleTextView.setText(getString(R.string.ConversationActivity_member_count,userCount));
|
||||||
} else if (PublicKeyValidation.isValid(recipient.getAddress().toString())) {
|
} else if (PublicKeyValidation.isValid(recipient.getAddress().toString())) {
|
||||||
subtitleTextView.setText(recipient.getAddress().toString());
|
subtitleTextView.setText(recipient.getAddress().toString());
|
||||||
} else {
|
} else {
|
||||||
@ -2411,7 +2381,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
private void updateMessageStatusProgressBar() {
|
private void updateMessageStatusProgressBar() {
|
||||||
if (messageStatus != null) {
|
if (messageStatus != null) {
|
||||||
messageStatusProgressBar.setAlpha(1.0f);
|
messageStatusProgressBar.setAlpha(1.0f);
|
||||||
switch (messageStatus) {
|
switch (messageStatus) {
|
||||||
case "calculatingPoW": setMessageStatusProgressAnimatedIfPossible(25); break;
|
case "calculatingPoW": setMessageStatusProgressAnimatedIfPossible(25); break;
|
||||||
case "contactingNetwork": setMessageStatusProgressAnimatedIfPossible(50); break;
|
case "contactingNetwork": setMessageStatusProgressAnimatedIfPossible(50); break;
|
||||||
@ -2448,7 +2418,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
default: return -1;
|
default: return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,17 +54,13 @@ import androidx.loader.content.Loader;
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
|
import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
||||||
import org.session.libsession.messaging.messages.control.DataExtractionNotification;
|
import org.session.libsession.messaging.messages.control.DataExtractionNotification;
|
||||||
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
|
||||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
import org.session.libsession.messaging.messages.visible.Quote;
|
import org.session.libsession.messaging.messages.visible.Quote;
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI;
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2;
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2;
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
@ -398,9 +394,8 @@ public class ConversationFragment extends Fragment
|
|||||||
boolean isGroupChat = recipient.isGroupRecipient();
|
boolean isGroupChat = recipient.isGroupRecipient();
|
||||||
|
|
||||||
if (isGroupChat) {
|
if (isGroupChat) {
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
|
||||||
OpenGroupV2 openGroupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getOpenGroupChat(threadId);
|
OpenGroupV2 openGroupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getOpenGroupChat(threadId);
|
||||||
boolean isPublicChat = (publicChat != null || openGroupChat != null);
|
boolean isPublicChat = (openGroupChat != null);
|
||||||
int selectedMessageCount = messageRecords.size();
|
int selectedMessageCount = messageRecords.size();
|
||||||
boolean areAllSentByUser = true;
|
boolean areAllSentByUser = true;
|
||||||
Set<String> uniqueUserSet = new HashSet<>();
|
Set<String> uniqueUserSet = new HashSet<>();
|
||||||
@ -412,10 +407,7 @@ public class ConversationFragment extends Fragment
|
|||||||
menu.findItem(R.id.menu_context_reply).setVisible(selectedMessageCount == 1);
|
menu.findItem(R.id.menu_context_reply).setVisible(selectedMessageCount == 1);
|
||||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(requireContext());
|
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(requireContext());
|
||||||
boolean userCanModerate =
|
boolean userCanModerate =
|
||||||
(isPublicChat &&
|
(isPublicChat && (OpenGroupAPIV2.isUserModerator(userHexEncodedPublicKey, openGroupChat.getRoom(), openGroupChat.getServer())));
|
||||||
((publicChat != null && OpenGroupAPI.isUserModerator(userHexEncodedPublicKey, publicChat.getChannel(), publicChat.getServer()))
|
|
||||||
|| (openGroupChat != null && OpenGroupAPIV2.isUserModerator(userHexEncodedPublicKey, openGroupChat.getRoom(), openGroupChat.getServer())))
|
|
||||||
);
|
|
||||||
boolean isDeleteOptionVisible = !isPublicChat || (areAllSentByUser || userCanModerate);
|
boolean isDeleteOptionVisible = !isPublicChat || (areAllSentByUser || userCanModerate);
|
||||||
// allow banning if moderating a public chat and only one user's messages are selected
|
// allow banning if moderating a public chat and only one user's messages are selected
|
||||||
boolean isBanOptionVisible = isPublicChat && userCanModerate && !areAllSentByUser && uniqueUserSet.size() == 1;
|
boolean isBanOptionVisible = isPublicChat && userCanModerate && !areAllSentByUser && uniqueUserSet.size() == 1;
|
||||||
@ -515,7 +507,6 @@ public class ConversationFragment extends Fragment
|
|||||||
builder.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messagesCount, messagesCount));
|
builder.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messagesCount, messagesCount));
|
||||||
builder.setCancelable(true);
|
builder.setCancelable(true);
|
||||||
|
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
|
||||||
OpenGroupV2 openGroupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getOpenGroupChat(threadId);
|
OpenGroupV2 openGroupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getOpenGroupChat(threadId);
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
||||||
@ -527,7 +518,7 @@ public class ConversationFragment extends Fragment
|
|||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(MessageRecord... messageRecords) {
|
protected Void doInBackground(MessageRecord... messageRecords) {
|
||||||
if (publicChat != null || openGroupChat != null) {
|
if (openGroupChat != null) {
|
||||||
ArrayList<Long> serverIDs = new ArrayList<>();
|
ArrayList<Long> serverIDs = new ArrayList<>();
|
||||||
ArrayList<Long> ignoredMessages = new ArrayList<>();
|
ArrayList<Long> ignoredMessages = new ArrayList<>();
|
||||||
ArrayList<Long> failedMessages = new ArrayList<>();
|
ArrayList<Long> failedMessages = new ArrayList<>();
|
||||||
@ -541,29 +532,7 @@ public class ConversationFragment extends Fragment
|
|||||||
ignoredMessages.add(messageRecord.getId());
|
ignoredMessages.add(messageRecord.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (publicChat != null) {
|
if (openGroupChat != null) {
|
||||||
OpenGroupAPI
|
|
||||||
.deleteMessages(serverIDs, publicChat.getChannel(), publicChat.getServer(), isSentByUser)
|
|
||||||
.success(l -> {
|
|
||||||
for (MessageRecord messageRecord : messageRecords) {
|
|
||||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id, !messageRecord.isMms());
|
|
||||||
if (l.contains(serverID)) {
|
|
||||||
if (messageRecord.isMms()) {
|
|
||||||
DatabaseFactory.getMmsDatabase(getActivity()).delete(messageRecord.getId());
|
|
||||||
} else {
|
|
||||||
DatabaseFactory.getSmsDatabase(getActivity()).deleteMessage(messageRecord.getId());
|
|
||||||
}
|
|
||||||
} else if (!ignoredMessages.contains(serverID)) {
|
|
||||||
failedMessages.add(messageRecord.getId());
|
|
||||||
Log.w("Loki", "Failed to delete message: " + messageRecord.getId() + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}). fail(e -> {
|
|
||||||
Log.w("Loki", "Couldn't delete message due to error: " + e.toString() + ".");
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
} else if (openGroupChat != null) {
|
|
||||||
for (Long serverId : serverIDs) {
|
for (Long serverId : serverIDs) {
|
||||||
OpenGroupAPIV2
|
OpenGroupAPIV2
|
||||||
.deleteMessage(serverId, openGroupChat.getRoom(), openGroupChat.getServer())
|
.deleteMessage(serverId, openGroupChat.getRoom(), openGroupChat.getServer())
|
||||||
@ -617,7 +586,6 @@ public class ConversationFragment extends Fragment
|
|||||||
builder.setTitle(R.string.ConversationFragment_ban_selected_user);
|
builder.setTitle(R.string.ConversationFragment_ban_selected_user);
|
||||||
builder.setCancelable(true);
|
builder.setCancelable(true);
|
||||||
|
|
||||||
final OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
|
||||||
final OpenGroupV2 openGroupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getOpenGroupChat(threadId);
|
final OpenGroupV2 openGroupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getOpenGroupChat(threadId);
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.ban, (dialog, which) -> {
|
builder.setPositiveButton(R.string.ban, (dialog, which) -> {
|
||||||
@ -630,17 +598,7 @@ public class ConversationFragment extends Fragment
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(String... userPublicKeyParam) {
|
protected Void doInBackground(String... userPublicKeyParam) {
|
||||||
String userPublicKey = userPublicKeyParam[0];
|
String userPublicKey = userPublicKeyParam[0];
|
||||||
if (publicChat != null) {
|
if (openGroupChat != null) {
|
||||||
OpenGroupAPI
|
|
||||||
.ban(userPublicKey, publicChat.getServer())
|
|
||||||
.success(l -> {
|
|
||||||
Log.d("Loki", "User banned");
|
|
||||||
return Unit.INSTANCE;
|
|
||||||
}).fail(e -> {
|
|
||||||
Log.e("Loki", "Couldn't ban user due to error",e);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
} else if (openGroupChat != null) {
|
|
||||||
OpenGroupAPIV2
|
OpenGroupAPIV2
|
||||||
.ban(userPublicKey, openGroupChat.getRoom(), openGroupChat.getServer())
|
.ban(userPublicKey, openGroupChat.getRoom(), openGroupChat.getServer())
|
||||||
.success(l -> {
|
.success(l -> {
|
||||||
|
@ -45,17 +45,14 @@ import android.widget.ImageView;
|
|||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.DimenRes;
|
import androidx.annotation.DimenRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob;
|
import org.session.libsession.messaging.jobs.AttachmentDownloadJob;
|
||||||
import org.session.libsession.messaging.jobs.JobQueue;
|
import org.session.libsession.messaging.jobs.JobQueue;
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI;
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2;
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2;
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
import org.session.libsession.messaging.open_groups.OpenGroupV2;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
||||||
@ -760,10 +757,6 @@ public class ConversationItem extends LinearLayout
|
|||||||
String publicKey = recipient.getAddress().toString();
|
String publicKey = recipient.getAddress().toString();
|
||||||
profilePictureView.setPublicKey(publicKey);
|
profilePictureView.setPublicKey(publicKey);
|
||||||
String displayName = recipient.getName();
|
String displayName = recipient.getName();
|
||||||
OpenGroup openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID);
|
|
||||||
if (displayName == null && openGroup != null) {
|
|
||||||
displayName = DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(openGroup.getId(), publicKey);
|
|
||||||
}
|
|
||||||
profilePictureView.setDisplayName(displayName);
|
profilePictureView.setDisplayName(displayName);
|
||||||
profilePictureView.setAdditionalPublicKey(null);
|
profilePictureView.setAdditionalPublicKey(null);
|
||||||
profilePictureView.setRSSFeed(false);
|
profilePictureView.setRSSFeed(false);
|
||||||
@ -898,19 +891,14 @@ public class ConversationItem extends LinearLayout
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private void setGroupMessageStatus(MessageRecord messageRecord, Recipient recipient) {
|
private void setGroupMessageStatus(MessageRecord messageRecord, Recipient recipient) {
|
||||||
if (groupThread && !messageRecord.isOutgoing()) {
|
if (groupThread && !messageRecord.isOutgoing()) {
|
||||||
// Show custom display names for group chats
|
String sessionID = recipient.getAddress().serialize();
|
||||||
String displayName = recipient.toShortString();
|
Contact contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(sessionID);
|
||||||
try {
|
String displayName;
|
||||||
String serverId = GroupUtil.getDecodedGroupID(conversationRecipient.getAddress().serialize());
|
if (contact != null) {
|
||||||
String senderDisplayName = DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(serverId, recipient.getAddress().serialize());
|
Contact.ContactContext context = (this.conversationRecipient.isOpenGroupRecipient()) ? Contact.ContactContext.OPEN_GROUP : Contact.ContactContext.REGULAR;
|
||||||
if (senderDisplayName != null) {
|
displayName = contact.displayName(context);
|
||||||
displayName = senderDisplayName;
|
} else {
|
||||||
} else {
|
displayName = sessionID;
|
||||||
// opengroupv2 format
|
|
||||||
displayName = OpenGroupUtilities.getDisplayName(recipient);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.groupSender.setText(displayName);
|
this.groupSender.setText(displayName);
|
||||||
@ -952,12 +940,8 @@ public class ConversationItem extends LinearLayout
|
|||||||
profilePictureView.setVisibility(VISIBLE);
|
profilePictureView.setVisibility(VISIBLE);
|
||||||
int visibility = View.GONE;
|
int visibility = View.GONE;
|
||||||
|
|
||||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
|
||||||
OpenGroupV2 openGroupV2 = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(messageRecord.getThreadId());
|
OpenGroupV2 openGroupV2 = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(messageRecord.getThreadId());
|
||||||
if (publicChat != null) {
|
if (openGroupV2 != null) {
|
||||||
boolean isModerator = OpenGroupAPI.isUserModerator(current.getRecipient().getAddress().toString(), publicChat.getChannel(), publicChat.getServer());
|
|
||||||
visibility = isModerator ? View.VISIBLE : View.GONE;
|
|
||||||
} else if (openGroupV2 != null) {
|
|
||||||
boolean isModerator = OpenGroupAPIV2.isUserModerator(current.getRecipient().getAddress().toString(), openGroupV2.getRoom(), openGroupV2.getServer());
|
boolean isModerator = OpenGroupAPIV2.isUserModerator(current.getRecipient().getAddress().toString(), openGroupV2.getRoom(), openGroupV2.getServer());
|
||||||
visibility = isModerator ? View.VISIBLE : View.GONE;
|
visibility = isModerator ? View.VISIBLE : View.GONE;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ public abstract class Database {
|
|||||||
public Database(Context context, SQLCipherOpenHelper databaseHelper) {
|
public Database(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.databaseHelper = databaseHelper;
|
this.databaseHelper = databaseHelper;
|
||||||
this.threadNotificationDebouncer = new Debouncer(ApplicationContext.getInstance(context).getThreadNotificationHandler(), 100);
|
this.threadNotificationDebouncer = new Debouncer(ApplicationContext.getInstance(context).getThreadNotificationHandler(), 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void notifyConversationListeners(Set<Long> threadIds) {
|
protected void notifyConversationListeners(Set<Long> threadIds) {
|
||||||
|
@ -17,11 +17,8 @@
|
|||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import net.sqlcipher.database.SQLiteDatabase;
|
import net.sqlcipher.database.SQLiteDatabase;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachmentProvider;
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachmentProvider;
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
||||||
@ -34,6 +31,7 @@ import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
|
|
||||||
public class DatabaseFactory {
|
public class DatabaseFactory {
|
||||||
|
|
||||||
@ -55,16 +53,13 @@ public class DatabaseFactory {
|
|||||||
private final GroupReceiptDatabase groupReceiptDatabase;
|
private final GroupReceiptDatabase groupReceiptDatabase;
|
||||||
private final SearchDatabase searchDatabase;
|
private final SearchDatabase searchDatabase;
|
||||||
private final JobDatabase jobDatabase;
|
private final JobDatabase jobDatabase;
|
||||||
|
|
||||||
// Loki
|
|
||||||
private final LokiAPIDatabase lokiAPIDatabase;
|
private final LokiAPIDatabase lokiAPIDatabase;
|
||||||
private final LokiMessageDatabase lokiMessageDatabase;
|
private final LokiMessageDatabase lokiMessageDatabase;
|
||||||
private final LokiThreadDatabase lokiThreadDatabase;
|
private final LokiThreadDatabase lokiThreadDatabase;
|
||||||
private final LokiUserDatabase lokiUserDatabase;
|
private final LokiUserDatabase lokiUserDatabase;
|
||||||
private final LokiBackupFilesDatabase lokiBackupFilesDatabase;
|
private final LokiBackupFilesDatabase lokiBackupFilesDatabase;
|
||||||
private final SessionJobDatabase sessionJobDatabase;
|
private final SessionJobDatabase sessionJobDatabase;
|
||||||
|
private final SessionContactDatabase sessionContactDatabase;
|
||||||
// Refactor
|
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
private final DatabaseAttachmentProvider attachmentProvider;
|
private final DatabaseAttachmentProvider attachmentProvider;
|
||||||
|
|
||||||
@ -157,6 +152,10 @@ public class DatabaseFactory {
|
|||||||
public static SessionJobDatabase getSessionJobDatabase(Context context) {
|
public static SessionJobDatabase getSessionJobDatabase(Context context) {
|
||||||
return getInstance(context).sessionJobDatabase;
|
return getInstance(context).sessionJobDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SessionContactDatabase getSessionContactDatabase(Context context) {
|
||||||
|
return getInstance(context).sessionContactDatabase;
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Refactor
|
// region Refactor
|
||||||
@ -202,6 +201,7 @@ public class DatabaseFactory {
|
|||||||
this.storage = new Storage(context, databaseHelper);
|
this.storage = new Storage(context, databaseHelper);
|
||||||
this.attachmentProvider = new DatabaseAttachmentProvider(context, databaseHelper);
|
this.attachmentProvider = new DatabaseAttachmentProvider(context, databaseHelper);
|
||||||
this.sessionJobDatabase = new SessionJobDatabase(context, databaseHelper);
|
this.sessionJobDatabase = new SessionJobDatabase(context, databaseHelper);
|
||||||
|
this.sessionContactDatabase = new SessionContactDatabase(context, databaseHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -248,6 +248,7 @@ public class RecipientDatabase extends Database {
|
|||||||
ContentValues contentValues = new ContentValues(1);
|
ContentValues contentValues = new ContentValues(1);
|
||||||
contentValues.put(SYSTEM_DISPLAY_NAME, profileName);
|
contentValues.put(SYSTEM_DISPLAY_NAME, profileName);
|
||||||
updateOrInsert(recipient.getAddress(), contentValues);
|
updateOrInsert(recipient.getAddress(), contentValues);
|
||||||
|
recipient.resolve().setName(profileName);
|
||||||
recipient.resolve().setProfileName(profileName);
|
recipient.resolve().setProfileName(profileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,18 +2,14 @@ package org.thoughtcrime.securesms.database
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import okhttp3.HttpUrl
|
|
||||||
import org.session.libsession.database.StorageProtocol
|
import org.session.libsession.database.StorageProtocol
|
||||||
import org.session.libsession.messaging.jobs.AttachmentUploadJob
|
import org.session.libsession.messaging.jobs.*
|
||||||
import org.session.libsession.messaging.jobs.Job
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
|
||||||
import org.session.libsession.messaging.jobs.MessageSendJob
|
|
||||||
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
||||||
import org.session.libsession.messaging.messages.signal.*
|
import org.session.libsession.messaging.messages.signal.*
|
||||||
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
||||||
import org.session.libsession.messaging.messages.visible.Attachment
|
import org.session.libsession.messaging.messages.visible.Attachment
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
@ -40,12 +36,12 @@ import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
|||||||
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
|
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol
|
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol
|
||||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.get
|
import org.thoughtcrime.securesms.loki.utilities.get
|
||||||
import org.thoughtcrime.securesms.loki.utilities.getString
|
import org.thoughtcrime.securesms.loki.utilities.getString
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||||
|
|
||||||
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
||||||
|
|
||||||
override fun getUserPublicKey(): String? {
|
override fun getUserPublicKey(): String? {
|
||||||
return TextSecurePreferences.getLocalNumber(context)
|
return TextSecurePreferences.getLocalNumber(context)
|
||||||
}
|
}
|
||||||
@ -72,30 +68,13 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return TextSecurePreferences.getProfilePictureURL(context)
|
return TextSecurePreferences.getProfilePictureURL(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setUserProfilePictureUrl(newProfilePicture: String) {
|
override fun setUserProfilePictureURL(newValue: String) {
|
||||||
val ourRecipient = Address.fromSerialized(getUserPublicKey()!!).let {
|
val ourRecipient = Address.fromSerialized(getUserPublicKey()!!).let {
|
||||||
Recipient.from(context, it, false)
|
Recipient.from(context, it, false)
|
||||||
}
|
}
|
||||||
TextSecurePreferences.setProfilePictureURL(context, newProfilePicture)
|
TextSecurePreferences.setProfilePictureURL(context, newValue)
|
||||||
RetrieveProfileAvatarJob(ourRecipient, newProfilePicture)
|
RetrieveProfileAvatarJob(ourRecipient, newValue)
|
||||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(ourRecipient, newProfilePicture))
|
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(ourRecipient, newValue))
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProfileKeyForRecipient(recipientPublicKey: String): ByteArray? {
|
|
||||||
val address = Address.fromSerialized(recipientPublicKey)
|
|
||||||
val recipient = Recipient.from(context, address, false)
|
|
||||||
return recipient.profileKey
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDisplayNameForRecipient(recipientPublicKey: String): String? {
|
|
||||||
val database = DatabaseFactory.getLokiUserDatabase(context)
|
|
||||||
return database.getDisplayName(recipientPublicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setProfileKeyForRecipient(recipientPublicKey: String, profileKey: ByteArray) {
|
|
||||||
val address = Address.fromSerialized(recipientPublicKey)
|
|
||||||
val recipient = Recipient.from(context, address, false)
|
|
||||||
DatabaseFactory.getRecipientDatabase(context).setProfileKey(recipient, profileKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOrGenerateRegistrationID(): Int {
|
override fun getOrGenerateRegistrationID(): Int {
|
||||||
@ -107,15 +86,15 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return registrationID
|
return registrationID
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun persistAttachments(messageId: Long, attachments: List<Attachment>): List<Long> {
|
override fun persistAttachments(messageID: Long, attachments: List<Attachment>): List<Long> {
|
||||||
val database = DatabaseFactory.getAttachmentDatabase(context)
|
val database = DatabaseFactory.getAttachmentDatabase(context)
|
||||||
val databaseAttachments = attachments.mapNotNull { it.toSignalAttachment() }
|
val databaseAttachments = attachments.mapNotNull { it.toSignalAttachment() }
|
||||||
return database.insertAttachments(messageId, databaseAttachments)
|
return database.insertAttachments(messageID, databaseAttachments)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttachmentsForMessage(messageId: Long): List<DatabaseAttachment> {
|
override fun getAttachmentsForMessage(messageID: Long): List<DatabaseAttachment> {
|
||||||
val database = DatabaseFactory.getAttachmentDatabase(context)
|
val database = DatabaseFactory.getAttachmentDatabase(context)
|
||||||
return database.getAttachmentsForMessage(messageId)
|
return database.getAttachmentsForMessage(messageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List<LinkPreview?>, groupPublicKey: String?, openGroupID: String?, attachments: List<Attachment>): Long? {
|
override fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List<LinkPreview?>, groupPublicKey: String?, openGroupID: String?, attachments: List<Attachment>): Long? {
|
||||||
@ -185,7 +164,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return messageID
|
return messageID
|
||||||
}
|
}
|
||||||
|
|
||||||
// JOBS
|
|
||||||
override fun persistJob(job: Job) {
|
override fun persistJob(job: Job) {
|
||||||
DatabaseFactory.getSessionJobDatabase(context).persistJob(job)
|
DatabaseFactory.getSessionJobDatabase(context).persistJob(job)
|
||||||
}
|
}
|
||||||
@ -210,6 +188,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return DatabaseFactory.getSessionJobDatabase(context).getMessageSendJob(messageSendJobID)
|
return DatabaseFactory.getSessionJobDatabase(context).getMessageSendJob(messageSendJobID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getMessageReceiveJob(messageReceiveJobID: String): MessageReceiveJob? {
|
||||||
|
return DatabaseFactory.getSessionJobDatabase(context).getMessageReceiveJob(messageReceiveJobID)
|
||||||
|
}
|
||||||
|
|
||||||
override fun resumeMessageSendJobIfNeeded(messageSendJobID: String) {
|
override fun resumeMessageSendJobIfNeeded(messageSendJobID: String) {
|
||||||
val job = DatabaseFactory.getSessionJobDatabase(context).getMessageSendJob(messageSendJobID) ?: return
|
val job = DatabaseFactory.getSessionJobDatabase(context).getMessageSendJob(messageSendJobID) ?: return
|
||||||
JobQueue.shared.add(job)
|
JobQueue.shared.add(job)
|
||||||
@ -219,20 +201,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return DatabaseFactory.getSessionJobDatabase(context).isJobCanceled(job)
|
return DatabaseFactory.getSessionJobDatabase(context).isJobCanceled(job)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorization
|
|
||||||
|
|
||||||
override fun getAuthToken(server: String): String? {
|
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getAuthToken(server)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setAuthToken(server: String, newValue: String?) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setAuthToken(server, newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun removeAuthToken(server: String) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setAuthToken(server, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAuthToken(room: String, server: String): String? {
|
override fun getAuthToken(room: String, server: String): String? {
|
||||||
val id = "$server.$room"
|
val id = "$server.$room"
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getAuthToken(id)
|
return DatabaseFactory.getLokiAPIDatabase(context).getAuthToken(id)
|
||||||
@ -248,30 +216,15 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getLokiAPIDatabase(context).setAuthToken(id, null)
|
DatabaseFactory.getLokiAPIDatabase(context).setAuthToken(id, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOpenGroup(threadID: String): OpenGroup? {
|
override fun getV2OpenGroup(threadId: Long): OpenGroupV2? {
|
||||||
if (threadID.toInt() < 0) { return null }
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
return database.get(LokiThreadDatabase.publicChatTable, "${LokiThreadDatabase.threadID} = ?", arrayOf(threadID)) { cursor ->
|
|
||||||
val publicChatAsJSON = cursor.getString(LokiThreadDatabase.publicChat)
|
|
||||||
OpenGroup.fromJSON(publicChatAsJSON)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getV2OpenGroup(threadId: String): OpenGroupV2? {
|
|
||||||
if (threadId.toInt() < 0) { return null }
|
if (threadId.toInt() < 0) { return null }
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(LokiThreadDatabase.publicChatTable, "${LokiThreadDatabase.threadID} = ?", arrayOf(threadId)) { cursor ->
|
return database.get(LokiThreadDatabase.publicChatTable, "${LokiThreadDatabase.threadID} = ?", arrayOf( threadId.toString() )) { cursor ->
|
||||||
val publicChatAsJson = cursor.getString(LokiThreadDatabase.publicChat)
|
val publicChatAsJson = cursor.getString(LokiThreadDatabase.publicChat)
|
||||||
OpenGroupV2.fromJSON(publicChatAsJson)
|
OpenGroupV2.fromJSON(publicChatAsJson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getThreadID(openGroupID: String): String {
|
|
||||||
val address = Address.fromSerialized(openGroupID)
|
|
||||||
val recipient = Recipient.from(context, address, false)
|
|
||||||
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient).toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpenGroupPublicKey(server: String): String? {
|
override fun getOpenGroupPublicKey(server: String): String? {
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getOpenGroupPublicKey(server)
|
return DatabaseFactory.getLokiAPIDatabase(context).getOpenGroupPublicKey(server)
|
||||||
}
|
}
|
||||||
@ -280,59 +233,27 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getLokiAPIDatabase(context).setOpenGroupPublicKey(server, newValue)
|
DatabaseFactory.getLokiAPIDatabase(context).setOpenGroupPublicKey(server, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setOpenGroupDisplayName(publicKey: String, channel: Long, server: String, displayName: String) {
|
override fun getLastMessageServerID(room: String, server: String): Long? {
|
||||||
val groupID = "$server.$channel"
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(groupID, publicKey, displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setOpenGroupDisplayName(publicKey: String, room: String, server: String, displayName: String) {
|
|
||||||
val groupID = "$server.$room"
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(groupID, publicKey, displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpenGroupDisplayName(publicKey: String, channel: Long, server: String): String? {
|
|
||||||
val groupID = "$server.$channel"
|
|
||||||
return DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(groupID, publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpenGroupDisplayName(publicKey: String, room: String, server: String): String? {
|
|
||||||
val groupID = "$server.$room"
|
|
||||||
return DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(groupID, publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLastMessageServerId(room: String, server: String): Long? {
|
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getLastMessageServerID(room, server)
|
return DatabaseFactory.getLokiAPIDatabase(context).getLastMessageServerID(room, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLastMessageServerId(room: String, server: String, newValue: Long) {
|
override fun setLastMessageServerID(room: String, server: String, newValue: Long) {
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setLastMessageServerID(room, server, newValue)
|
DatabaseFactory.getLokiAPIDatabase(context).setLastMessageServerID(room, server, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeLastMessageServerId(room: String, server: String) {
|
override fun removeLastMessageServerID(room: String, server: String) {
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(room, server)
|
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(room, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastMessageServerID(group: Long, server: String): Long? {
|
override fun getLastDeletionServerID(room: String, server: String): Long? {
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getLastMessageServerID(group, server)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLastMessageServerID(group: Long, server: String, newValue: Long) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setLastMessageServerID(group, server, newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun removeLastMessageServerID(group: Long, server: String) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(group, server)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLastDeletionServerId(room: String, server: String): Long? {
|
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getLastDeletionServerID(room, server)
|
return DatabaseFactory.getLokiAPIDatabase(context).getLastDeletionServerID(room, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLastDeletionServerId(room: String, server: String, newValue: Long) {
|
override fun setLastDeletionServerID(room: String, server: String, newValue: Long) {
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setLastDeletionServerID(room, server, newValue)
|
DatabaseFactory.getLokiAPIDatabase(context).setLastDeletionServerID(room, server, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeLastDeletionServerId(room: String, server: String) {
|
override fun removeLastDeletionServerID(room: String, server: String) {
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(room, server)
|
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(room, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,34 +261,15 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getLokiAPIDatabase(context).setUserCount(room, server, newValue)
|
DatabaseFactory.getLokiAPIDatabase(context).setUserCount(room, server, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastDeletionServerID(group: Long, server: String): Long? {
|
override fun setOpenGroupServerMessageID(messageID: Long, serverID: Long, threadID: Long, isSms: Boolean) {
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getLastDeletionServerID(group, server)
|
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID, isSms)
|
||||||
}
|
DatabaseFactory.getLokiMessageDatabase(context).setOriginalThreadID(messageID, serverID, threadID)
|
||||||
|
|
||||||
override fun setLastDeletionServerID(group: Long, server: String, newValue: Long) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setLastDeletionServerID(group, server, newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun removeLastDeletionServerID(group: Long, server: String) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(group, server)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isDuplicateMessage(timestamp: Long): Boolean {
|
override fun isDuplicateMessage(timestamp: Long): Boolean {
|
||||||
return getReceivedMessageTimestamps().contains(timestamp)
|
return getReceivedMessageTimestamps().contains(timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setUserCount(group: Long, server: String, newValue: Int) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setUserCount(group, server, newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setOpenGroupProfilePictureURL(group: Long, server: String, newValue: String) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setOpenGroupProfilePictureURL(group, server, newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpenGroupProfilePictureURL(group: Long, server: String): String? {
|
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getOpenGroupProfilePictureURL(group, server)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateTitle(groupID: String, newValue: String) {
|
override fun updateTitle(groupID: String, newValue: String) {
|
||||||
DatabaseFactory.getGroupDatabase(context).updateTitle(groupID, newValue)
|
DatabaseFactory.getGroupDatabase(context).updateTitle(groupID, newValue)
|
||||||
}
|
}
|
||||||
@ -394,15 +296,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return database.getMessageFor(timestamp, address)?.getId()
|
return database.getMessageFor(timestamp, address)?.getId()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setOpenGroupServerMessageID(messageID: Long, serverID: Long, threadID: Long, isSms: Boolean) {
|
|
||||||
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID, isSms)
|
|
||||||
DatabaseFactory.getLokiMessageDatabase(context).setOriginalThreadID(messageID, serverID, threadID)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getQuoteServerID(quoteID: Long, publicKey: String): Long? {
|
|
||||||
return DatabaseFactory.getLokiMessageDatabase(context).getQuoteServerID(quoteID, publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun markAsSent(timestamp: Long, author: String) {
|
override fun markAsSent(timestamp: Long, author: String) {
|
||||||
val database = DatabaseFactory.getMmsSmsDatabase(context)
|
val database = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
val messageRecord = database.getMessageFor(timestamp, author) ?: return
|
val messageRecord = database.getMessageFor(timestamp, author) ?: return
|
||||||
@ -461,7 +354,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getGroupDatabase(context).setActive(groupID, value)
|
DatabaseFactory.getGroupDatabase(context).setActive(groupID, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getZombieMember(groupID: String): Set<String> {
|
override fun getZombieMembers(groupID: String): Set<String> {
|
||||||
return DatabaseFactory.getGroupDatabase(context).getGroupZombieMembers(groupID).map { it.address.serialize() }.toHashSet()
|
return DatabaseFactory.getGroupDatabase(context).getGroupZombieMembers(groupID).map { it.address.serialize() }.toHashSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +366,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
|
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateZombieMembers(groupID: String, members: List<Address>) {
|
override fun setZombieMembers(groupID: String, members: List<Address>) {
|
||||||
DatabaseFactory.getGroupDatabase(context).updateZombieMembers(groupID, members)
|
DatabaseFactory.getGroupDatabase(context).updateZombieMembers(groupID, members)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,39 +432,18 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getLokiAPIDatabase(context).removeAllClosedGroupEncryptionKeyPairs(groupPublicKey)
|
DatabaseFactory.getLokiAPIDatabase(context).removeAllClosedGroupEncryptionKeyPairs(groupPublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAllOpenGroups(): Map<Long, OpenGroup> {
|
|
||||||
return DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChats().mapValues { (_,chat)->
|
|
||||||
OpenGroup(chat.channel, chat.server, chat.displayName, chat.isDeletable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAllV2OpenGroups(): Map<Long, OpenGroupV2> {
|
override fun getAllV2OpenGroups(): Map<Long, OpenGroupV2> {
|
||||||
return DatabaseFactory.getLokiThreadDatabase(context).getAllV2OpenGroups()
|
return DatabaseFactory.getLokiThreadDatabase(context).getAllV2OpenGroups()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addOpenGroup(serverUrl: String, channel: Long) {
|
|
||||||
val httpUrl = HttpUrl.parse(serverUrl) ?: return
|
|
||||||
if (httpUrl.queryParameterNames().contains("public_key")) {
|
|
||||||
// open group v2
|
|
||||||
val server = HttpUrl.Builder().scheme(httpUrl.scheme()).host(httpUrl.host()).apply {
|
|
||||||
if (httpUrl.port() != 80 || httpUrl.port() != 443) {
|
|
||||||
// non-standard port, add to server
|
|
||||||
this.port(httpUrl.port())
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
val room = httpUrl.pathSegments().firstOrNull() ?: return
|
|
||||||
val publicKey = httpUrl.queryParameter("public_key") ?: return
|
|
||||||
|
|
||||||
OpenGroupManager.add(server.toString().removeSuffix("/"), room, publicKey, context)
|
|
||||||
} else {
|
|
||||||
// TODO: No longer supported so let's remove this code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAllGroups(): List<GroupRecord> {
|
override fun getAllGroups(): List<GroupRecord> {
|
||||||
return DatabaseFactory.getGroupDatabase(context).allGroups
|
return DatabaseFactory.getGroupDatabase(context).allGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun addOpenGroup(urlAsString: String) {
|
||||||
|
OpenGroupManager.addOpenGroup(urlAsString, context)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setProfileSharing(address: Address, value: Boolean) {
|
override fun setProfileSharing(address: Address, value: Boolean) {
|
||||||
val recipient = Recipient.from(context, address, false)
|
val recipient = Recipient.from(context, address, false)
|
||||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, value)
|
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, value)
|
||||||
@ -596,8 +468,17 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getThreadIdFor(address: Address): Long? {
|
override fun getThreadId(publicKeyOrOpenGroupID: String): Long? {
|
||||||
|
val address = Address.fromSerialized(publicKeyOrOpenGroupID)
|
||||||
|
return getThreadId(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getThreadId(address: Address): Long? {
|
||||||
val recipient = Recipient.from(context, address, false)
|
val recipient = Recipient.from(context, address, false)
|
||||||
|
return getThreadId(recipient)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getThreadId(recipient: Recipient): Long? {
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient)
|
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient)
|
||||||
return if (threadID < 0) null else threadID
|
return if (threadID < 0) null else threadID
|
||||||
}
|
}
|
||||||
@ -611,36 +492,16 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return threadId
|
return threadId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSessionRequestSentTimestamp(publicKey: String): Long? {
|
override fun getContactWithSessionID(sessionID: String): Contact? {
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getSessionRequestSentTimestamp(publicKey)
|
return DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(sessionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSessionRequestSentTimestamp(publicKey: String, newValue: Long) {
|
override fun getAllContacts(): Set<Contact> {
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setSessionRequestSentTimestamp(publicKey, newValue)
|
return DatabaseFactory.getSessionContactDatabase(context).getAllContacts()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSessionRequestProcessedTimestamp(publicKey: String): Long? {
|
override fun setContact(contact: Contact) {
|
||||||
return DatabaseFactory.getLokiAPIDatabase(context).getSessionRequestProcessedTimestamp(publicKey)
|
DatabaseFactory.getSessionContactDatabase(context).setContact(contact)
|
||||||
}
|
|
||||||
|
|
||||||
override fun setSessionRequestProcessedTimestamp(publicKey: String, newValue: Long) {
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setSessionRequestProcessedTimestamp(publicKey, newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDisplayName(publicKey: String): String? {
|
|
||||||
return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setDisplayName(publicKey: String, newName: String) {
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setDisplayName(publicKey, newName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getServerDisplayName(serverID: String, publicKey: String): String? {
|
|
||||||
return DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(serverID, publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProfilePictureURL(publicKey: String): String? {
|
|
||||||
return DatabaseFactory.getLokiUserDatabase(context).getProfilePictureURL(publicKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRecipientSettings(address: Address): Recipient.RecipientSettings? {
|
override fun getRecipientSettings(address: Address): Recipient.RecipientSettings? {
|
||||||
@ -669,10 +530,15 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
threadDatabase.getOrCreateThreadIdFor(recipient)
|
threadDatabase.getOrCreateThreadIdFor(recipient)
|
||||||
}
|
}
|
||||||
if (contacts.isNotEmpty()) {
|
if (contacts.isNotEmpty()) {
|
||||||
threadDatabase.notifyUpdatedFromConfig()
|
threadDatabase.notifyConversationListListeners()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLastUpdated(threadID: Long): Long {
|
||||||
|
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||||
|
return threadDB.getLastUpdated(threadID)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getAttachmentDataUri(attachmentId: AttachmentId): Uri {
|
override fun getAttachmentDataUri(attachmentId: AttachmentId): Uri {
|
||||||
return PartAuthority.getAttachmentDataUri(attachmentId)
|
return PartAuthority.getAttachmentDataUri(attachmentId)
|
||||||
}
|
}
|
||||||
@ -681,7 +547,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
return PartAuthority.getAttachmentThumbnailUri(attachmentId)
|
return PartAuthority.getAttachmentThumbnailUri(attachmentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data Extraction Notification
|
|
||||||
override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long) {
|
override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long) {
|
||||||
val database = DatabaseFactory.getMmsDatabase(context)
|
val database = DatabaseFactory.getMmsDatabase(context)
|
||||||
val address = fromSerialized(senderPublicKey)
|
val address = fromSerialized(senderPublicKey)
|
||||||
|
@ -64,7 +64,7 @@ public class ThreadDatabase extends Database {
|
|||||||
|
|
||||||
private static final String TAG = ThreadDatabase.class.getSimpleName();
|
private static final String TAG = ThreadDatabase.class.getSimpleName();
|
||||||
|
|
||||||
private Map<Long, Address> addressCache = new HashMap<>();
|
private final Map<Long, Address> addressCache = new HashMap<>();
|
||||||
|
|
||||||
public static final String TABLE_NAME = "thread";
|
public static final String TABLE_NAME = "thread";
|
||||||
public static final String ID = "_id";
|
public static final String ID = "_id";
|
||||||
@ -404,6 +404,21 @@ public class ThreadDatabase extends Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getLastUpdated(long threadId) {
|
||||||
|
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||||
|
Cursor cursor = db.query(TABLE_NAME, new String[]{DATE}, ID_WHERE, new String[]{String.valueOf(threadId)}, null, null, null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
return cursor.getLong(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1L;
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteConversation(long threadId) {
|
public void deleteConversation(long threadId) {
|
||||||
DatabaseFactory.getSmsDatabase(context).deleteThread(threadId);
|
DatabaseFactory.getSmsDatabase(context).deleteThread(threadId);
|
||||||
DatabaseFactory.getMmsDatabase(context).deleteThread(threadId);
|
DatabaseFactory.getMmsDatabase(context).deleteThread(threadId);
|
||||||
@ -471,7 +486,6 @@ public class ThreadDatabase extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable Recipient getRecipientForThreadId(long threadId) {
|
public @Nullable Recipient getRecipientForThreadId(long threadId) {
|
||||||
// Loki - Cache the address
|
|
||||||
if (addressCache.containsKey(threadId) && addressCache.get(threadId) != null) {
|
if (addressCache.containsKey(threadId) && addressCache.get(threadId) != null) {
|
||||||
return Recipient.from(context, addressCache.get(threadId), false);
|
return Recipient.from(context, addressCache.get(threadId), false);
|
||||||
}
|
}
|
||||||
@ -505,10 +519,6 @@ public class ThreadDatabase extends Database {
|
|||||||
notifyConversationListeners(threadId);
|
notifyConversationListeners(threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyUpdatedFromConfig() {
|
|
||||||
notifyConversationListListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean update(long threadId, boolean unarchive) {
|
public boolean update(long threadId, boolean unarchive) {
|
||||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||||
long count = mmsSmsDatabase.getConversationCount(threadId);
|
long count = mmsSmsDatabase.getConversationCount(threadId);
|
||||||
|
@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
|
||||||
|
|
||||||
@ -56,9 +57,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
private static final int lokiV22 = 43;
|
private static final int lokiV22 = 43;
|
||||||
private static final int lokiV23 = 44;
|
private static final int lokiV23 = 44;
|
||||||
private static final int lokiV24 = 45;
|
private static final int lokiV24 = 45;
|
||||||
|
private static final int lokiV25 = 46;
|
||||||
|
private static final int lokiV26 = 47;
|
||||||
|
|
||||||
// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||||
private static final int DATABASE_VERSION = lokiV24;
|
private static final int DATABASE_VERSION = lokiV26;
|
||||||
private static final String DATABASE_NAME = "signal.db";
|
private static final String DATABASE_NAME = "signal.db";
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -123,11 +126,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
|
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
|
||||||
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
|
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
|
||||||
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
|
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
|
||||||
db.execSQL(LokiUserDatabase.getCreateServerDisplayNameTableCommand());
|
|
||||||
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
||||||
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
||||||
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());
|
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());
|
||||||
db.execSQL(LokiMessageDatabase.getUpdateMessageMappingTable());
|
db.execSQL(LokiMessageDatabase.getUpdateMessageMappingTable());
|
||||||
|
db.execSQL(SessionContactDatabase.getCreateSessionContactTableCommand());
|
||||||
|
|
||||||
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
||||||
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
||||||
@ -291,6 +294,16 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.execSQL(LokiAPIDatabase.getCreateSwarmTableCommand());
|
db.execSQL(LokiAPIDatabase.getCreateSwarmTableCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < lokiV25) {
|
||||||
|
String jobTable = SessionJobDatabase.sessionJobTable;
|
||||||
|
db.execSQL("DROP TABLE " + jobTable);
|
||||||
|
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldVersion < lokiV26) {
|
||||||
|
db.execSQL(SessionContactDatabase.getCreateSessionContactTableCommand());
|
||||||
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
|
@ -92,7 +92,7 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType {
|
|||||||
SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, Optional.of(0), Optional.absent(), 0, 0, digest, fileName, false, Optional.absent(), url);
|
SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, Optional.of(0), Optional.absent(), 0, 0, digest, fileName, false, Optional.absent(), url);
|
||||||
|
|
||||||
if (pointer.getUrl().isEmpty()) throw new InvalidMessageException("Missing attachment URL.");
|
if (pointer.getUrl().isEmpty()) throw new InvalidMessageException("Missing attachment URL.");
|
||||||
DownloadUtilities.downloadFile(attachment, pointer.getUrl(), MAX_AVATAR_SIZE, null);
|
DownloadUtilities.downloadFile(attachment, pointer.getUrl());
|
||||||
|
|
||||||
// Assume we're retrieving an attachment for an open group server if the digest is not set
|
// Assume we're retrieving an attachment for an open group server if the digest is not set
|
||||||
InputStream inputStream;
|
InputStream inputStream;
|
||||||
|
@ -100,7 +100,7 @@ public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType
|
|||||||
File downloadDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
|
File downloadDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DownloadUtilities.downloadFile(downloadDestination, profileAvatar, MAX_PROFILE_SIZE_BYTES, null);
|
DownloadUtilities.downloadFile(downloadDestination, profileAvatar);
|
||||||
InputStream avatarStream = new ProfileCipherInputStream(new FileInputStream(downloadDestination), profileKey);
|
InputStream avatarStream = new ProfileCipherInputStream(new FileInputStream(downloadDestination), profileKey);
|
||||||
File decryptDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
|
File decryptDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ActivityBackupRestoreBinding
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
import org.thoughtcrime.securesms.backup.FullBackupImporter
|
import org.thoughtcrime.securesms.backup.FullBackupImporter
|
||||||
@ -61,31 +60,31 @@ class BackupRestoreActivity : BaseActionBarActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setUpActionBarSessionLogo()
|
setUpActionBarSessionLogo()
|
||||||
|
|
||||||
val viewBinding = DataBindingUtil.setContentView<ActivityBackupRestoreBinding>(this, R.layout.activity_backup_restore)
|
// val viewBinding = DataBindingUtil.setContentView<ActivityBackupRestoreBinding>(this, R.layout.activity_backup_restore)
|
||||||
viewBinding.lifecycleOwner = this
|
// viewBinding.lifecycleOwner = this
|
||||||
viewBinding.viewModel = viewModel
|
// viewBinding.viewModel = viewModel
|
||||||
|
|
||||||
viewBinding.restoreButton.setOnClickListener { viewModel.tryRestoreBackup() }
|
// viewBinding.restoreButton.setOnClickListener { viewModel.tryRestoreBackup() }
|
||||||
|
|
||||||
viewBinding.buttonSelectFile.setOnClickListener {
|
// viewBinding.buttonSelectFile.setOnClickListener {
|
||||||
fileSelectionResultLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
// fileSelectionResultLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||||
//FIXME On some old APIs (tested on 21 & 23) the mime type doesn't filter properly
|
// //FIXME On some old APIs (tested on 21 & 23) the mime type doesn't filter properly
|
||||||
// and the backup files are unavailable for selection.
|
// // and the backup files are unavailable for selection.
|
||||||
// type = BackupUtil.BACKUP_FILE_MIME_TYPE
|
//// type = BackupUtil.BACKUP_FILE_MIME_TYPE
|
||||||
type = "*/*"
|
// type = "*/*"
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
viewBinding.backupCode.addTextChangedListener { text -> viewModel.backupPassphrase.value = text.toString() }
|
// viewBinding.backupCode.addTextChangedListener { text -> viewModel.backupPassphrase.value = text.toString() }
|
||||||
|
|
||||||
// Focus passphrase text edit when backup file is selected.
|
// Focus passphrase text edit when backup file is selected.
|
||||||
viewModel.backupFile.observe(this, { backupFile ->
|
// viewModel.backupFile.observe(this, { backupFile ->
|
||||||
if (backupFile != null) viewBinding.backupCode.post {
|
// if (backupFile != null) viewBinding.backupCode.post {
|
||||||
viewBinding.backupCode.requestFocus()
|
// viewBinding.backupCode.requestFocus()
|
||||||
(getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
|
// (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
|
||||||
.showSoftInput(viewBinding.backupCode, InputMethodManager.SHOW_IMPLICIT)
|
// .showSoftInput(viewBinding.backupCode, InputMethodManager.SHOW_IMPLICIT)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
// React to backup import result.
|
// React to backup import result.
|
||||||
viewModel.backupImportResult.observe(this) { result ->
|
viewModel.backupImportResult.observe(this) { result ->
|
||||||
@ -116,8 +115,8 @@ class BackupRestoreActivity : BaseActionBarActivity() {
|
|||||||
openURL("https://getsession.org/privacy-policy/")
|
openURL("https://getsession.org/privacy-policy/")
|
||||||
}
|
}
|
||||||
}, 61, 75, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
}, 61, 75, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
viewBinding.termsTextView.movementMethod = LinkMovementMethod.getInstance()
|
// viewBinding.termsTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||||
viewBinding.termsTextView.text = termsExplanation
|
// viewBinding.termsTextView.text = termsExplanation
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +189,6 @@ class BackupRestoreViewModel(application: Application): AndroidViewModel(applica
|
|||||||
TextSecurePreferences.setHasViewedSeed(context, true)
|
TextSecurePreferences.setHasViewedSeed(context, true)
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(context, true)
|
TextSecurePreferences.setHasSeenWelcomeScreen(context, true)
|
||||||
val application = ApplicationContext.getInstance(context)
|
val application = ApplicationContext.getInstance(context)
|
||||||
application.setUpStorageAPIIfNeeded()
|
|
||||||
|
|
||||||
BackupRestoreResult.SUCCESS
|
BackupRestoreResult.SUCCESS
|
||||||
} catch (e: DatabaseDowngradeException) {
|
} catch (e: DatabaseDowngradeException) {
|
||||||
|
@ -30,8 +30,8 @@ import org.greenrobot.eventbus.Subscribe
|
|||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.messaging.mentions.MentionsManager
|
import org.session.libsession.messaging.mentions.MentionsManager
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||||
|
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPollerV2
|
||||||
import org.session.libsession.utilities.*
|
import org.session.libsession.utilities.*
|
||||||
import org.session.libsignal.utilities.toHexString
|
import org.session.libsignal.utilities.toHexString
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
@ -133,12 +133,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
})
|
})
|
||||||
// Set up remaining components if needed
|
// Set up remaining components if needed
|
||||||
val application = ApplicationContext.getInstance(this)
|
val application = ApplicationContext.getInstance(this)
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(this)
|
|
||||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
|
||||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
MentionsManager.configureIfNeeded(userPublicKey, userDB)
|
|
||||||
OpenGroupManager.startPolling()
|
OpenGroupManager.startPolling()
|
||||||
JobQueue.shared.resumePendingJobs()
|
JobQueue.shared.resumePendingJobs()
|
||||||
}
|
}
|
||||||
@ -332,16 +328,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete the conversation
|
// Delete the conversation
|
||||||
val v1OpenGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
|
||||||
val v2OpenGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
|
val v2OpenGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
|
||||||
if (v1OpenGroup != null) {
|
if (v2OpenGroup != null) {
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
|
||||||
apiDB.removeLastMessageServerID(v1OpenGroup.channel, v1OpenGroup.server)
|
|
||||||
apiDB.removeLastDeletionServerID(v1OpenGroup.channel, v1OpenGroup.server)
|
|
||||||
apiDB.clearOpenGroupProfilePictureURL(v1OpenGroup.channel, v1OpenGroup.server)
|
|
||||||
OpenGroupAPI.leave(v1OpenGroup.channel, v1OpenGroup.server)
|
|
||||||
// FIXME: No longer supported so let's remove this code
|
|
||||||
} else if (v2OpenGroup != null) {
|
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
||||||
apiDB.removeLastMessageServerID(v2OpenGroup.room, v2OpenGroup.server)
|
apiDB.removeLastMessageServerID(v2OpenGroup.room, v2OpenGroup.server)
|
||||||
apiDB.removeLastDeletionServerID(v2OpenGroup.room, v2OpenGroup.server)
|
apiDB.removeLastDeletionServerID(v2OpenGroup.room, v2OpenGroup.server)
|
||||||
|
@ -29,6 +29,7 @@ import org.session.libsession.utilities.DistributionTypes
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.PublicKeyValidation
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||||
@ -37,7 +38,6 @@ import org.thoughtcrime.securesms.loki.api.OpenGroupManager
|
|||||||
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
||||||
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragmentDelegate
|
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragmentDelegate
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
|
||||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
|
||||||
import org.thoughtcrime.securesms.loki.viewmodel.DefaultGroupsViewModel
|
import org.thoughtcrime.securesms.loki.viewmodel.DefaultGroupsViewModel
|
||||||
import org.thoughtcrime.securesms.loki.viewmodel.State
|
import org.thoughtcrime.securesms.loki.viewmodel.State
|
||||||
|
|
||||||
@ -86,6 +86,9 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
|||||||
val room = url.pathSegments().firstOrNull()
|
val room = url.pathSegments().firstOrNull()
|
||||||
val publicKey = url.queryParameter("public_key")
|
val publicKey = url.queryParameter("public_key")
|
||||||
val isV2OpenGroup = !room.isNullOrEmpty()
|
val isV2OpenGroup = !room.isNullOrEmpty()
|
||||||
|
if (isV2OpenGroup && (publicKey == null || !PublicKeyValidation.isValid(publicKey, 64,false))) {
|
||||||
|
return Toast.makeText(this, R.string.invalid_public_key, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
showLoader()
|
showLoader()
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
|
@ -122,7 +122,6 @@ class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDel
|
|||||||
}
|
}
|
||||||
// start polling and wait for updated message
|
// start polling and wait for updated message
|
||||||
ApplicationContext.getInstance(this@LinkDeviceActivity).apply {
|
ApplicationContext.getInstance(this@LinkDeviceActivity).apply {
|
||||||
setUpStorageAPIIfNeeded()
|
|
||||||
startPollingIfNeeded()
|
startPollingIfNeeded()
|
||||||
}
|
}
|
||||||
TextSecurePreferences.events.filter { it == TextSecurePreferences.CONFIGURATION_SYNCED }.collect {
|
TextSecurePreferences.events.filter { it == TextSecurePreferences.CONFIGURATION_SYNCED }.collect {
|
||||||
|
@ -43,6 +43,7 @@ class PNModeActivity : BaseActionBarActivity() {
|
|||||||
backgroundPollingOptionView.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
|
backgroundPollingOptionView.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
|
||||||
backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
|
backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
|
||||||
registerButton.setOnClickListener { register() }
|
registerButton.setOnClickListener { register() }
|
||||||
|
toggleFCM()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
@ -153,7 +154,6 @@ class PNModeActivity : BaseActionBarActivity() {
|
|||||||
}
|
}
|
||||||
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
|
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
|
||||||
val application = ApplicationContext.getInstance(this)
|
val application = ApplicationContext.getInstance(this)
|
||||||
application.setUpStorageAPIIfNeeded()
|
|
||||||
application.startPollingIfNeeded()
|
application.startPollingIfNeeded()
|
||||||
application.registerForFCMIfNeeded(true)
|
application.registerForFCMIfNeeded(true)
|
||||||
val intent = Intent(this, HomeActivity::class.java)
|
val intent = Intent(this, HomeActivity::class.java)
|
||||||
|
@ -26,7 +26,6 @@ import nl.komponents.kovenant.all
|
|||||||
import nl.komponents.kovenant.ui.alwaysUi
|
import nl.komponents.kovenant.ui.alwaysUi
|
||||||
import nl.komponents.kovenant.ui.successUi
|
import nl.komponents.kovenant.ui.successUi
|
||||||
import org.session.libsession.avatars.AvatarHelper
|
import org.session.libsession.avatars.AvatarHelper
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.ProfilePictureUtilities
|
import org.session.libsession.utilities.ProfilePictureUtilities
|
||||||
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
|
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
|
||||||
@ -73,7 +72,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||||
super.onCreate(savedInstanceState, isReady)
|
super.onCreate(savedInstanceState, isReady)
|
||||||
setContentView(R.layout.activity_settings)
|
setContentView(R.layout.activity_settings)
|
||||||
val displayName = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey)
|
val displayName = TextSecurePreferences.getProfileName(this) ?: hexEncodedPublicKey
|
||||||
glide = GlideApp.with(this)
|
glide = GlideApp.with(this)
|
||||||
profilePictureView.glide = glide
|
profilePictureView.glide = glide
|
||||||
profilePictureView.publicKey = hexEncodedPublicKey
|
profilePictureView.publicKey = hexEncodedPublicKey
|
||||||
@ -179,8 +178,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
val promises = mutableListOf<Promise<*, Exception>>()
|
val promises = mutableListOf<Promise<*, Exception>>()
|
||||||
val displayName = displayNameToBeUploaded
|
val displayName = displayNameToBeUploaded
|
||||||
if (displayName != null) {
|
if (displayName != null) {
|
||||||
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
|
|
||||||
promises.addAll(servers.map { OpenGroupAPI.setDisplayName(displayName, it) })
|
|
||||||
TextSecurePreferences.setProfileName(this, displayName)
|
TextSecurePreferences.setProfileName(this, displayName)
|
||||||
}
|
}
|
||||||
val profilePicture = profilePictureToBeUploaded
|
val profilePicture = profilePictureToBeUploaded
|
||||||
@ -195,7 +192,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt())
|
TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt())
|
||||||
TextSecurePreferences.setLastProfilePictureUpload(this, Date().time)
|
TextSecurePreferences.setLastProfilePictureUpload(this, Date().time)
|
||||||
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
|
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
|
||||||
ApplicationContext.getInstance(this).updateOpenGroupProfilePicturesIfNeeded()
|
|
||||||
}
|
}
|
||||||
if (profilePicture != null || displayName != null) {
|
if (profilePicture != null || displayName != null) {
|
||||||
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@SettingsActivity)
|
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@SettingsActivity)
|
||||||
|
@ -7,9 +7,9 @@ import androidx.work.*
|
|||||||
import nl.komponents.kovenant.Promise
|
import nl.komponents.kovenant.Promise
|
||||||
import nl.komponents.kovenant.all
|
import nl.komponents.kovenant.all
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPoller
|
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPollerV2
|
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPollerV2
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
@ -57,7 +57,10 @@ class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Wor
|
|||||||
promises.addAll(dmsPromise.get())
|
promises.addAll(dmsPromise.get())
|
||||||
|
|
||||||
// Closed groups
|
// Closed groups
|
||||||
promises.addAll(ClosedGroupPoller().pollOnce())
|
val closedGroupPoller = ClosedGroupPollerV2() // Intentionally don't use shared
|
||||||
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
|
val allGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
|
||||||
|
allGroupPublicKeys.forEach { closedGroupPoller.poll(it) }
|
||||||
|
|
||||||
// Open Groups
|
// Open Groups
|
||||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||||
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.loki.api
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
|
import okhttp3.HttpUrl
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
||||||
@ -19,7 +20,22 @@ object OpenGroupManager {
|
|||||||
private var pollers = mutableMapOf<String, OpenGroupPollerV2>() // One for each server
|
private var pollers = mutableMapOf<String, OpenGroupPollerV2>() // One for each server
|
||||||
private var isPolling = false
|
private var isPolling = false
|
||||||
|
|
||||||
var isAllCaughtUp = false
|
val isAllCaughtUp: Boolean
|
||||||
|
get() {
|
||||||
|
pollers.values.forEach { poller ->
|
||||||
|
val jobID = poller.secondToLastJob?.id
|
||||||
|
jobID?.let {
|
||||||
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
|
if (storage.getMessageReceiveJob(jobID) == null) {
|
||||||
|
// If the second to last job is done, it means we are now handling the last job
|
||||||
|
poller.isCaughtUp = true
|
||||||
|
poller.secondToLastJob = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!poller.isCaughtUp) { return false }
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun startPolling() {
|
fun startPolling() {
|
||||||
if (isPolling) { return }
|
if (isPolling) { return }
|
||||||
@ -49,8 +65,8 @@ object OpenGroupManager {
|
|||||||
val existingOpenGroup = threadDB.getOpenGroupChat(threadID)
|
val existingOpenGroup = threadDB.getOpenGroupChat(threadID)
|
||||||
if (existingOpenGroup != null) { return }
|
if (existingOpenGroup != null) { return }
|
||||||
// Clear any existing data if needed
|
// Clear any existing data if needed
|
||||||
storage.removeLastDeletionServerId(room, server)
|
storage.removeLastDeletionServerID(room, server)
|
||||||
storage.removeLastMessageServerId(room, server)
|
storage.removeLastMessageServerID(room, server)
|
||||||
// Store the public key
|
// Store the public key
|
||||||
storage.setOpenGroupPublicKey(server,publicKey)
|
storage.setOpenGroupPublicKey(server,publicKey)
|
||||||
// Get an auth token
|
// Get an auth token
|
||||||
@ -85,7 +101,8 @@ object OpenGroupManager {
|
|||||||
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||||
val openGroupID = "$server.$room"
|
val openGroupID = "$server.$room"
|
||||||
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context)
|
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context)
|
||||||
val groupID = threadDB.getRecipientForThreadId(threadID)!!.address.serialize()
|
val recipient = threadDB.getRecipientForThreadId(threadID) ?: return
|
||||||
|
val groupID = recipient.address.serialize()
|
||||||
// Stop the poller if needed
|
// Stop the poller if needed
|
||||||
val openGroups = storage.getAllV2OpenGroups().filter { it.value.server == server }
|
val openGroups = storage.getAllV2OpenGroups().filter { it.value.server == server }
|
||||||
if (openGroups.count() == 1) {
|
if (openGroups.count() == 1) {
|
||||||
@ -95,9 +112,22 @@ object OpenGroupManager {
|
|||||||
}
|
}
|
||||||
// Delete
|
// Delete
|
||||||
ThreadUtils.queue {
|
ThreadUtils.queue {
|
||||||
storage.removeLastDeletionServerId(room, server)
|
storage.removeLastDeletionServerID(room, server)
|
||||||
storage.removeLastMessageServerId(room, server)
|
storage.removeLastMessageServerID(room, server)
|
||||||
GroupManager.deleteGroup(groupID, context) // Must be invoked on a background thread
|
GroupManager.deleteGroup(groupID, context) // Must be invoked on a background thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addOpenGroup(urlAsString: String, context: Context) {
|
||||||
|
val url = HttpUrl.parse(urlAsString) ?: return
|
||||||
|
val builder = HttpUrl.Builder().scheme(url.scheme()).host(url.host())
|
||||||
|
if (url.port() != 80 || url.port() != 443) {
|
||||||
|
// Non-standard port; add to server
|
||||||
|
builder.port(url.port())
|
||||||
|
}
|
||||||
|
val server = builder.build()
|
||||||
|
val room = url.pathSegments().firstOrNull() ?: return
|
||||||
|
val publicKey = url.queryParameter("public_key") ?: return
|
||||||
|
add(server.toString().removeSuffix("/"), room, publicKey, context)
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.loki.api
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
||||||
|
|
||||||
@ -57,36 +56,16 @@ class PublicChatInfoUpdateWorker(val context: Context, params: WorkerParameters)
|
|||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
val serverUrl = inputData.getString(DATA_KEY_SERVER_URL)!!
|
val serverUrl = inputData.getString(DATA_KEY_SERVER_URL)!!
|
||||||
val channel = inputData.getLong(DATA_KEY_CHANNEL, -1)
|
|
||||||
val room = inputData.getString(DATA_KEY_ROOM)
|
val room = inputData.getString(DATA_KEY_ROOM)
|
||||||
|
val openGroupId = "$serverUrl.$room"
|
||||||
val isOpenGroupV2 = !room.isNullOrEmpty() && channel == -1L
|
return try {
|
||||||
|
Log.v(TAG, "Updating open group info for $openGroupId.")
|
||||||
if (!isOpenGroupV2) {
|
OpenGroupUtilities.updateGroupInfo(context, serverUrl, room!!)
|
||||||
val publicChatId = OpenGroup.getId(channel, serverUrl)
|
Log.v(TAG, "Open group info was successfully updated for $openGroupId.")
|
||||||
|
Result.success()
|
||||||
return try {
|
} catch (e: Exception) {
|
||||||
Log.v(TAG, "Updating open group info for $publicChatId.")
|
Log.e(TAG, "Failed to update open group info for $openGroupId", e)
|
||||||
OpenGroupUtilities.updateGroupInfo(context, serverUrl, channel)
|
Result.failure()
|
||||||
Log.v(TAG, "Open group info was successfully updated for $publicChatId.")
|
|
||||||
Result.success()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to update open group info for $publicChatId", e)
|
|
||||||
Result.failure()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val openGroupId = "$serverUrl.$room"
|
|
||||||
|
|
||||||
return try {
|
|
||||||
Log.v(TAG, "Updating open group info for $openGroupId.")
|
|
||||||
OpenGroupUtilities.updateGroupInfo(context, serverUrl, room!!)
|
|
||||||
Log.v(TAG, "Open group info was successfully updated for $openGroupId.")
|
|
||||||
Result.success()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to update open group info for $openGroupId", e)
|
|
||||||
Result.failure()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,14 +278,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastMessageServerID(group: Long, server: String): Long? {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
return database.get(lastMessageServerIDTable, "$lastMessageServerIDTableIndex = ?", wrap(index)) { cursor ->
|
|
||||||
cursor.getInt(lastMessageServerID)
|
|
||||||
}?.toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLastMessageServerID(room: String, server: String): Long? {
|
override fun getLastMessageServerID(room: String, server: String): Long? {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val index = "$server.$room"
|
val index = "$server.$room"
|
||||||
@ -294,13 +286,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
}?.toLong()
|
}?.toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLastMessageServerID(group: Long, server: String, newValue: Long) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
val row = wrap(mapOf( lastMessageServerIDTableIndex to index, lastMessageServerID to newValue.toString() ))
|
|
||||||
database.insertOrUpdate(lastMessageServerIDTable, row, "$lastMessageServerIDTableIndex = ?", wrap(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLastMessageServerID(room: String, server: String, newValue: Long) {
|
override fun setLastMessageServerID(room: String, server: String, newValue: Long) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val index = "$server.$room"
|
val index = "$server.$room"
|
||||||
@ -308,26 +293,12 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
database.insertOrUpdate(lastMessageServerIDTable, row, "$lastMessageServerIDTableIndex = ?", wrap(index))
|
database.insertOrUpdate(lastMessageServerIDTable, row, "$lastMessageServerIDTableIndex = ?", wrap(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeLastMessageServerID(group: Long, server: String) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
database.delete(lastMessageServerIDTable,"$lastMessageServerIDTableIndex = ?", wrap(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeLastMessageServerID(room: String, server:String) {
|
fun removeLastMessageServerID(room: String, server:String) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val index = "$server.$room"
|
val index = "$server.$room"
|
||||||
database.delete(lastMessageServerIDTable, "$lastMessageServerIDTableIndex = ?", wrap(index))
|
database.delete(lastMessageServerIDTable, "$lastMessageServerIDTableIndex = ?", wrap(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastDeletionServerID(group: Long, server: String): Long? {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
return database.get(lastDeletionServerIDTable, "$lastDeletionServerIDTableIndex = ?", wrap(index)) { cursor ->
|
|
||||||
cursor.getInt(lastDeletionServerID)
|
|
||||||
}?.toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLastDeletionServerID(room: String, server: String): Long? {
|
override fun getLastDeletionServerID(room: String, server: String): Long? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
val index = "$server.$room"
|
val index = "$server.$room"
|
||||||
@ -336,13 +307,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
}?.toLong()
|
}?.toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLastDeletionServerID(group: Long, server: String, newValue: Long) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
val row = wrap(mapOf( lastDeletionServerIDTableIndex to index, lastDeletionServerID to newValue.toString() ))
|
|
||||||
database.insertOrUpdate(lastDeletionServerIDTable, row, "$lastDeletionServerIDTableIndex = ?", wrap(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLastDeletionServerID(room: String, server: String, newValue: Long) {
|
override fun setLastDeletionServerID(room: String, server: String, newValue: Long) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val index = "$server.$room"
|
val index = "$server.$room"
|
||||||
@ -392,32 +356,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
database.insertOrUpdate(userCountTable, row, "$publicChatID = ?", wrap(index))
|
database.insertOrUpdate(userCountTable, row, "$publicChatID = ?", wrap(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSessionRequestSentTimestamp(publicKey: String): Long? {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
return database.get(sessionRequestSentTimestampTable, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey)) { cursor ->
|
|
||||||
cursor.getLong(LokiAPIDatabase.timestamp)
|
|
||||||
}?.toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setSessionRequestSentTimestamp(publicKey: String, newValue: Long) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val row = wrap(mapOf( LokiAPIDatabase.publicKey to publicKey, LokiAPIDatabase.timestamp to newValue.toString() ))
|
|
||||||
database.insertOrUpdate(sessionRequestSentTimestampTable, row, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSessionRequestProcessedTimestamp(publicKey: String): Long? {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
return database.get(sessionRequestProcessedTimestampTable, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey)) { cursor ->
|
|
||||||
cursor.getInt(LokiAPIDatabase.timestamp)
|
|
||||||
}?.toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setSessionRequestProcessedTimestamp(publicKey: String, newValue: Long) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val row = wrap(mapOf(LokiAPIDatabase.publicKey to publicKey, LokiAPIDatabase.timestamp to newValue.toString()))
|
|
||||||
database.insertOrUpdate(sessionRequestProcessedTimestampTable, row, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpenGroupPublicKey(server: String): String? {
|
override fun getOpenGroupPublicKey(server: String): String? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(openGroupPublicKeyTable, "${LokiAPIDatabase.server} = ?", wrap(server)) { cursor ->
|
return database.get(openGroupPublicKeyTable, "${LokiAPIDatabase.server} = ?", wrap(server)) { cursor ->
|
||||||
@ -431,27 +369,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
database.insertOrUpdate(openGroupPublicKeyTable, row, "${LokiAPIDatabase.server} = ?", wrap(server))
|
database.insertOrUpdate(openGroupPublicKeyTable, row, "${LokiAPIDatabase.server} = ?", wrap(server))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOpenGroupProfilePictureURL(group: Long, server: String): String? {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
return database.get(openGroupProfilePictureTable, "$publicChatID = ?", wrap(index)) { cursor ->
|
|
||||||
cursor.getString(openGroupProfilePicture)
|
|
||||||
}?.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setOpenGroupProfilePictureURL(group: Long, server: String, newValue: String) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
val row = wrap(mapOf(publicChatID to index, openGroupProfilePicture to newValue))
|
|
||||||
database.insertOrUpdate(openGroupProfilePictureTable, row, "$publicChatID = ?", wrap(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearOpenGroupProfilePictureURL(group: Long, server: String): Boolean {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val index = "$server.$group"
|
|
||||||
return database.delete(openGroupProfilePictureTable, "$publicChatID = ?", arrayOf(index)) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLastSnodePoolRefreshDate(): Date? {
|
override fun getLastSnodePoolRefreshDate(): Date? {
|
||||||
val time = TextSecurePreferences.getLastSnodePoolRefreshDate(context)
|
val time = TextSecurePreferences.getLastSnodePoolRefreshDate(context)
|
||||||
if (time <= 0) { return null }
|
if (time <= 0) { return null }
|
||||||
|
@ -37,11 +37,6 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getQuoteServerID(quoteID: Long, quoteePublicKey: String): Long? {
|
|
||||||
val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, quoteePublicKey)
|
|
||||||
return if (message != null) getServerID(message.getId(), !message.isMms) else null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getServerID(messageID: Long): Long? {
|
fun getServerID(messageID: Long): Long? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(messageIDTable, "${Companion.messageID} = ?", arrayOf(messageID.toString())) { cursor ->
|
return database.get(messageIDTable, "${Companion.messageID} = ?", arrayOf(messageID.toString())) { cursor ->
|
||||||
|
@ -3,17 +3,13 @@ package org.thoughtcrime.securesms.loki.database
|
|||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
import org.thoughtcrime.securesms.loki.utilities.*
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
|
|
||||||
import org.session.libsignal.utilities.JsonUtil
|
import org.session.libsignal.utilities.JsonUtil
|
||||||
|
|
||||||
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||||
@ -22,7 +18,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
private val sessionResetTable = "loki_thread_session_reset_database"
|
private val sessionResetTable = "loki_thread_session_reset_database"
|
||||||
val publicChatTable = "loki_public_chat_database"
|
val publicChatTable = "loki_public_chat_database"
|
||||||
val threadID = "thread_id"
|
val threadID = "thread_id"
|
||||||
private val friendRequestStatus = "friend_request_status"
|
|
||||||
private val sessionResetStatus = "session_reset_status"
|
private val sessionResetStatus = "session_reset_status"
|
||||||
val publicChat = "public_chat"
|
val publicChat = "public_chat"
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -37,28 +32,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllPublicChats(): Map<Long, OpenGroup> {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
var cursor: Cursor? = null
|
|
||||||
val result = mutableMapOf<Long, OpenGroup>()
|
|
||||||
try {
|
|
||||||
cursor = database.rawQuery("select * from $publicChatTable", null)
|
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
|
||||||
val threadID = cursor.getLong(threadID)
|
|
||||||
val string = cursor.getString(publicChat)
|
|
||||||
val publicChat = OpenGroup.fromJSON(string)
|
|
||||||
if (publicChat != null) {
|
|
||||||
result[threadID] = publicChat
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
// Do nothing
|
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllV2OpenGroups(): Map<Long, OpenGroupV2> {
|
fun getAllV2OpenGroups(): Map<Long, OpenGroupV2> {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
@ -79,20 +52,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllPublicChatServers(): Set<String> {
|
|
||||||
return getAllPublicChats().values.fold(setOf()) { set, chat -> set.plus(chat.server) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPublicChat(threadID: Long): OpenGroup? {
|
|
||||||
if (threadID < 0) { return null }
|
|
||||||
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
return database.get(publicChatTable, "${Companion.threadID} = ?", arrayOf(threadID.toString())) { cursor ->
|
|
||||||
val publicChatAsJSON = cursor.getString(publicChat)
|
|
||||||
OpenGroup.fromJSON(publicChatAsJSON)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOpenGroupChat(threadID: Long): OpenGroupV2? {
|
fun getOpenGroupChat(threadID: Long): OpenGroupV2? {
|
||||||
if (threadID < 0) {
|
if (threadID < 0) {
|
||||||
return null
|
return null
|
||||||
@ -114,19 +73,4 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
contentValues.put(publicChat, JsonUtil.toJson(openGroupV2.toJson()))
|
contentValues.put(publicChat, JsonUtil.toJson(openGroupV2.toJson()))
|
||||||
database.insertOrUpdate(publicChatTable, contentValues, "${Companion.threadID} = ?", arrayOf(threadID.toString()))
|
database.insertOrUpdate(publicChatTable, contentValues, "${Companion.threadID} = ?", arrayOf(threadID.toString()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setPublicChat(publicChat: OpenGroup, threadID: Long) {
|
|
||||||
if (threadID < 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val contentValues = ContentValues(2)
|
|
||||||
contentValues.put(Companion.threadID, threadID)
|
|
||||||
contentValues.put(Companion.publicChat, JsonUtil.toJson(publicChat.toJSON()))
|
|
||||||
database.insertOrUpdate(publicChatTable, contentValues, "${Companion.threadID} = ?", arrayOf(threadID.toString()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removePublicChat(threadID: Long) {
|
|
||||||
databaseHelper.writableDatabase.delete(publicChatTable, "${Companion.threadID} = ?", arrayOf(threadID.toString()))
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,19 +1,12 @@
|
|||||||
package org.thoughtcrime.securesms.loki.database
|
package org.thoughtcrime.securesms.loki.database
|
||||||
|
|
||||||
import android.content.ContentValues
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.sqlite.SQLiteDatabase
|
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.session.libsession.utilities.Address
|
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
import org.thoughtcrime.securesms.loki.utilities.get
|
import org.thoughtcrime.securesms.loki.utilities.get
|
||||||
import org.thoughtcrime.securesms.loki.utilities.insertOrUpdate
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.database.LokiUserDatabaseProtocol
|
|
||||||
|
|
||||||
class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiUserDatabaseProtocol {
|
class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Shared
|
// Shared
|
||||||
@ -28,7 +21,7 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
|
|||||||
@JvmStatic val createServerDisplayNameTableCommand = "CREATE TABLE $serverDisplayNameTable ($publicKey TEXT, $serverID TEXT, $displayName TEXT, PRIMARY KEY ($publicKey, $serverID));"
|
@JvmStatic val createServerDisplayNameTableCommand = "CREATE TABLE $serverDisplayNameTable ($publicKey TEXT, $serverID TEXT, $displayName TEXT, PRIMARY KEY ($publicKey, $serverID));"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDisplayName(publicKey: String): String? {
|
fun getDisplayName(publicKey: String): String? {
|
||||||
if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||||
return TextSecurePreferences.getProfileName(context)
|
return TextSecurePreferences.getProfileName(context)
|
||||||
} else {
|
} else {
|
||||||
@ -44,42 +37,4 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDisplayName(publicKey: String, displayName: String) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val row = ContentValues(2)
|
|
||||||
row.put(Companion.publicKey, publicKey)
|
|
||||||
row.put(Companion.displayName, displayName)
|
|
||||||
database.insertOrUpdate(displayNameTable, row, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
|
||||||
Recipient.from(context, Address.fromSerialized(publicKey), false).notifyListeners()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getServerDisplayName(serverID: String, publicKey: String): String? {
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
return database.get(serverDisplayNameTable, "${Companion.publicKey} = ? AND ${Companion.serverID} = ?", arrayOf( publicKey, serverID )) { cursor ->
|
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setServerDisplayName(serverID: String, publicKey: String, displayName: String) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val values = ContentValues(3)
|
|
||||||
values.put(Companion.serverID, serverID)
|
|
||||||
values.put(Companion.publicKey, publicKey)
|
|
||||||
values.put(Companion.displayName, displayName)
|
|
||||||
try {
|
|
||||||
database.insertWithOnConflict(serverDisplayNameTable, null, values, SQLiteDatabase.CONFLICT_REPLACE)
|
|
||||||
Recipient.from(context, Address.fromSerialized(publicKey), false).notifyListeners()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.d("Loki", "Couldn't save server display name due to exception: $e.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProfilePictureURL(publicKey: String): String? {
|
|
||||||
return if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
|
||||||
TextSecurePreferences.getProfilePictureURL(context)
|
|
||||||
} else {
|
|
||||||
Recipient.from(context, Address.fromSerialized(publicKey), false).resolve().profileAvatar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.database
|
||||||
|
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.content.Context
|
||||||
|
import net.sqlcipher.Cursor
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
|
import org.session.libsignal.utilities.Base64
|
||||||
|
import org.thoughtcrime.securesms.database.Database
|
||||||
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
|
|
||||||
|
class SessionContactDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val sessionContactTable = "session_contact_database"
|
||||||
|
const val sessionID = "session_id"
|
||||||
|
const val name = "name"
|
||||||
|
const val nickname = "nickname"
|
||||||
|
const val profilePictureURL = "profile_picture_url"
|
||||||
|
const val profilePictureFileName = "profile_picture_file_name"
|
||||||
|
const val profilePictureEncryptionKey = "profile_picture_encryption_key"
|
||||||
|
const val threadID = "thread_id"
|
||||||
|
const val isTrusted = "is_trusted"
|
||||||
|
@JvmStatic val createSessionContactTableCommand =
|
||||||
|
"CREATE TABLE $sessionContactTable " +
|
||||||
|
"($sessionID STRING PRIMARY KEY, " +
|
||||||
|
"$name TEXT DEFAULT NULL, " +
|
||||||
|
"$nickname TEXT DEFAULT NULL, " +
|
||||||
|
"$profilePictureURL TEXT DEFAULT NULL, " +
|
||||||
|
"$profilePictureFileName TEXT DEFAULT NULL, " +
|
||||||
|
"$profilePictureEncryptionKey BLOB DEFAULT NULL, " +
|
||||||
|
"$threadID INTEGER DEFAULT -1, " +
|
||||||
|
"$isTrusted INTEGER DEFAULT 0);"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getContactWithSessionID(sessionID: String): Contact? {
|
||||||
|
val database = databaseHelper.readableDatabase
|
||||||
|
return database.get(sessionContactTable, "${SessionContactDatabase.sessionID} = ?", arrayOf( sessionID )) { cursor ->
|
||||||
|
contactFromCursor(cursor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllContacts(): Set<Contact> {
|
||||||
|
val database = databaseHelper.readableDatabase
|
||||||
|
return database.getAll(sessionContactTable, null, null) { cursor ->
|
||||||
|
contactFromCursor(cursor)
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setContact(contact: Contact) {
|
||||||
|
val database = databaseHelper.writableDatabase
|
||||||
|
val contentValues = ContentValues(8)
|
||||||
|
contentValues.put(sessionID, contact.sessionID)
|
||||||
|
contentValues.put(name, contact.name)
|
||||||
|
contentValues.put(nickname, contact.nickname)
|
||||||
|
contentValues.put(profilePictureURL, contact.profilePictureURL)
|
||||||
|
contentValues.put(profilePictureFileName, contact.profilePictureFileName)
|
||||||
|
contact.profilePictureEncryptionKey?.let {
|
||||||
|
contentValues.put(profilePictureEncryptionKey, Base64.encodeBytes(it))
|
||||||
|
}
|
||||||
|
contentValues.put(threadID, threadID)
|
||||||
|
contentValues.put(isTrusted, if (contact.isTrusted) 1 else 0)
|
||||||
|
database.insertOrUpdate(sessionContactTable, contentValues, "$sessionID = ?", arrayOf( contact.sessionID ))
|
||||||
|
notifyConversationListListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun contactFromCursor(cursor: Cursor): Contact {
|
||||||
|
val sessionID = cursor.getString(sessionID)
|
||||||
|
val contact = Contact(sessionID)
|
||||||
|
contact.name = cursor.getStringOrNull(name)
|
||||||
|
contact.nickname = cursor.getStringOrNull(nickname)
|
||||||
|
contact.profilePictureURL = cursor.getStringOrNull(profilePictureURL)
|
||||||
|
contact.profilePictureFileName = cursor.getStringOrNull(profilePictureFileName)
|
||||||
|
cursor.getStringOrNull(profilePictureEncryptionKey)?.let {
|
||||||
|
contact.profilePictureEncryptionKey = Base64.decode(it)
|
||||||
|
}
|
||||||
|
contact.threadID = cursor.getLong(threadID)
|
||||||
|
contact.isTrusted = cursor.getInt(isTrusted) != 0
|
||||||
|
return contact
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.loki.utilities.*
|
|||||||
class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val sessionJobTable = "session_job_database"
|
const val sessionJobTable = "session_job_database"
|
||||||
const val jobID = "job_id"
|
const val jobID = "job_id"
|
||||||
const val jobType = "job_type"
|
const val jobType = "job_type"
|
||||||
const val failureCount = "failure_count"
|
const val failureCount = "failure_count"
|
||||||
@ -71,6 +71,13 @@ class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getMessageReceiveJob(messageReceiveJobID: String): MessageReceiveJob? {
|
||||||
|
val database = databaseHelper.readableDatabase
|
||||||
|
return database.get(sessionJobTable, "$jobID = ? AND $jobType = ?", arrayOf( messageReceiveJobID, MessageReceiveJob.KEY )) { cursor ->
|
||||||
|
jobFromCursor(cursor) as MessageReceiveJob?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun cancelPendingMessageSendJobs(threadID: Long) {
|
fun cancelPendingMessageSendJobs(threadID: Long) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val attachmentUploadJobKeys = mutableListOf<String>()
|
val attachmentUploadJobKeys = mutableListOf<String>()
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.dialogs
|
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
||||||
import kotlinx.android.synthetic.main.fragment_key_pair_migration_bottom_sheet.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
|
|
||||||
class KeyPairMigrationBottomSheet : BottomSheetDialogFragment() {
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_key_pair_migration_bottom_sheet, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
upgradeNowButton.setOnClickListener { upgradeNow() }
|
|
||||||
upgradeLaterButton.setOnClickListener { upgradeLater() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
||||||
val dialog = super.onCreateDialog(savedInstanceState)
|
|
||||||
dialog.setOnShowListener {
|
|
||||||
val d = dialog as BottomSheetDialog
|
|
||||||
val bottomSheet = d.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)!!
|
|
||||||
BottomSheetBehavior.from(bottomSheet).state = BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
BottomSheetBehavior.from(bottomSheet).isHideable = false
|
|
||||||
}
|
|
||||||
isCancelable = false
|
|
||||||
return dialog
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun upgradeNow() {
|
|
||||||
val applicationContext = requireContext().applicationContext as ApplicationContext
|
|
||||||
applicationContext.clearAllData(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun upgradeLater() {
|
|
||||||
val dialog = AlertDialog.Builder(requireContext())
|
|
||||||
dialog.setMessage("You won't be able to send or receive messages until you upgrade.")
|
|
||||||
dialog.setPositiveButton(R.string.ok) { _, _ ->
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
dialog.create().show()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.dialogs
|
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
||||||
import kotlinx.android.synthetic.main.fragment_key_pair_migration_success_bottom_sheet.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
|
||||||
|
|
||||||
class KeyPairMigrationSuccessBottomSheet : BottomSheetDialogFragment() {
|
|
||||||
|
|
||||||
private val sessionID by lazy {
|
|
||||||
TextSecurePreferences.getLocalNumber(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_key_pair_migration_success_bottom_sheet, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
sessionIDTextView.text = sessionID
|
|
||||||
copyButton.setOnClickListener { copySessionID() }
|
|
||||||
okButton.setOnClickListener { dismiss() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
||||||
val dialog = super.onCreateDialog(savedInstanceState)
|
|
||||||
// Expand the bottom sheet by default
|
|
||||||
dialog.setOnShowListener {
|
|
||||||
val d = dialog as BottomSheetDialog
|
|
||||||
val bottomSheet = d.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
|
|
||||||
BottomSheetBehavior.from(bottomSheet!!).setState(BottomSheetBehavior.STATE_EXPANDED);
|
|
||||||
}
|
|
||||||
return dialog
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copySessionID() {
|
|
||||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val clip = ClipData.newPlainText("Session ID", sessionID)
|
|
||||||
clipboard.setPrimaryClip(clip)
|
|
||||||
Toast.makeText(requireContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.loki.dialogs
|
package org.thoughtcrime.securesms.loki.dialogs
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -8,14 +9,19 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import kotlinx.android.synthetic.main.fragment_user_details_bottom_sheet.*
|
import kotlinx.android.synthetic.main.fragment_user_details_bottom_sheet.*
|
||||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
|
import org.session.libsession.utilities.Address
|
||||||
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
|
|
||||||
public class UserDetailsBottomSheet : BottomSheetDialogFragment() {
|
class UserDetailsBottomSheet : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_user_details_bottom_sheet, container, false)
|
return inflater.inflate(R.layout.fragment_user_details_bottom_sheet, container, false)
|
||||||
@ -24,11 +30,38 @@ public class UserDetailsBottomSheet : BottomSheetDialogFragment() {
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val publicKey = arguments?.getString("publicKey") ?: return dismiss()
|
val publicKey = arguments?.getString("publicKey") ?: return dismiss()
|
||||||
|
val recipient = Recipient.from(requireContext(), Address.fromSerialized(publicKey), false)
|
||||||
profilePictureView.publicKey = publicKey
|
profilePictureView.publicKey = publicKey
|
||||||
profilePictureView.glide = GlideApp.with(this)
|
profilePictureView.glide = GlideApp.with(this)
|
||||||
profilePictureView.isLarge = true
|
profilePictureView.isLarge = true
|
||||||
profilePictureView.update()
|
profilePictureView.update()
|
||||||
nameTextView.text = DatabaseFactory.getLokiUserDatabase(requireContext()).getDisplayName(publicKey) ?: "Anonymous"
|
nameTextViewContainer.visibility = View.VISIBLE
|
||||||
|
nameTextViewContainer.setOnClickListener {
|
||||||
|
nameTextViewContainer.visibility = View.INVISIBLE
|
||||||
|
nameEditTextContainer.visibility = View.VISIBLE
|
||||||
|
nicknameEditText.text = null
|
||||||
|
nicknameEditText.requestFocus()
|
||||||
|
showSoftKeyboard()
|
||||||
|
}
|
||||||
|
cancelNicknameEditingButton.setOnClickListener {
|
||||||
|
nicknameEditText.clearFocus()
|
||||||
|
hideSoftKeyboard()
|
||||||
|
nameTextViewContainer.visibility = View.VISIBLE
|
||||||
|
nameEditTextContainer.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
saveNicknameButton.setOnClickListener {
|
||||||
|
saveNickName(recipient)
|
||||||
|
}
|
||||||
|
nicknameEditText.setOnEditorActionListener { _, actionId, _ ->
|
||||||
|
when (actionId) {
|
||||||
|
EditorInfo.IME_ACTION_DONE -> {
|
||||||
|
saveNickName(recipient)
|
||||||
|
return@setOnEditorActionListener true
|
||||||
|
}
|
||||||
|
else -> return@setOnEditorActionListener false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nameTextView.text = recipient.name ?: publicKey // Uses the Contact API internally
|
||||||
publicKeyTextView.text = publicKey
|
publicKeyTextView.text = publicKey
|
||||||
copyButton.setOnClickListener {
|
copyButton.setOnClickListener {
|
||||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
@ -37,4 +70,32 @@ public class UserDetailsBottomSheet : BottomSheetDialogFragment() {
|
|||||||
Toast.makeText(requireContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveNickName(recipient: Recipient) {
|
||||||
|
nicknameEditText.clearFocus()
|
||||||
|
hideSoftKeyboard()
|
||||||
|
nameTextViewContainer.visibility = View.VISIBLE
|
||||||
|
nameEditTextContainer.visibility = View.INVISIBLE
|
||||||
|
var newNickName: String? = null
|
||||||
|
if (nicknameEditText.text.isNotEmpty()) {
|
||||||
|
newNickName = nicknameEditText.text.toString()
|
||||||
|
}
|
||||||
|
val publicKey = recipient.address.serialize()
|
||||||
|
val contactDB = DatabaseFactory.getSessionContactDatabase(context)
|
||||||
|
val contact = contactDB.getContactWithSessionID(publicKey) ?: Contact(publicKey)
|
||||||
|
contact.nickname = newNickName
|
||||||
|
contactDB.setContact(contact)
|
||||||
|
nameTextView.text = recipient.name ?: publicKey // Uses the Contact API internally
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ServiceCast")
|
||||||
|
fun showSoftKeyboard() {
|
||||||
|
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
|
||||||
|
imm?.showSoftInput(nicknameEditText, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideSoftKeyboard() {
|
||||||
|
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
|
||||||
|
imm?.hideSoftInputFromWindow(nicknameEditText.windowToken, 0)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,15 +1,8 @@
|
|||||||
package org.thoughtcrime.securesms.loki.protocol
|
package org.thoughtcrime.securesms.loki.protocol
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
|
||||||
import org.session.libsignal.messages.SignalServiceContent
|
|
||||||
import org.session.libsignal.messages.SignalServiceDataMessage
|
import org.session.libsignal.messages.SignalServiceDataMessage
|
||||||
import java.security.MessageDigest
|
|
||||||
|
|
||||||
object SessionMetaProtocol {
|
object SessionMetaProtocol {
|
||||||
|
|
||||||
@ -39,43 +32,6 @@ object SessionMetaProtocol {
|
|||||||
return shouldIgnoreMessage
|
return shouldIgnoreMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun shouldIgnoreDecryptionException(context: Context, timestamp: Long): Boolean {
|
|
||||||
val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
|
|
||||||
return timestamp <= restorationTimestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) {
|
|
||||||
val displayName = content.senderDisplayName.orNull() ?: return
|
|
||||||
if (displayName.isBlank()) { return }
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
val sender = content.sender.toLowerCase()
|
|
||||||
if (userPublicKey == sender) {
|
|
||||||
// Update the user's local name if the message came from their master device
|
|
||||||
TextSecurePreferences.setProfileName(context, displayName)
|
|
||||||
}
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun handleProfileKeyUpdate(context: Context, content: SignalServiceContent) {
|
|
||||||
val message = content.dataMessage.get()
|
|
||||||
if (!message.profileKey.isPresent) { return }
|
|
||||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(content.sender), false)
|
|
||||||
if (recipient.profileKey == null || !MessageDigest.isEqual(recipient.profileKey, message.profileKey.get())) {
|
|
||||||
database.setProfileKey(recipient, message.profileKey.get())
|
|
||||||
database.setUnidentifiedAccessMode(recipient, Recipient.UnidentifiedAccessMode.UNKNOWN)
|
|
||||||
val url = content.senderProfilePictureURL.or("")
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(recipient, url))
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
if (userPublicKey == content.sender) {
|
|
||||||
ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun canUserReplyToNotification(recipient: Recipient): Boolean {
|
fun canUserReplyToNotification(recipient: Recipient): Boolean {
|
||||||
// TODO return !recipient.address.isRSSFeed
|
// TODO return !recipient.address.isRSSFeed
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.loki.utilities
|
package org.thoughtcrime.securesms.loki.utilities
|
||||||
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
|
import androidx.core.database.getStringOrNull
|
||||||
import net.sqlcipher.Cursor
|
import net.sqlcipher.Cursor
|
||||||
import net.sqlcipher.database.SQLiteDatabase
|
import net.sqlcipher.database.SQLiteDatabase
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
@ -57,3 +58,7 @@ fun Cursor.getLong(columnName: String): Long {
|
|||||||
fun Cursor.getBase64EncodedData(columnName: String): ByteArray {
|
fun Cursor.getBase64EncodedData(columnName: String): ByteArray {
|
||||||
return Base64.decode(getString(columnName))
|
return Base64.decode(getString(columnName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Cursor.getStringOrNull(columnName: String): String? {
|
||||||
|
return getStringOrNull(getColumnIndexOrThrow(columnName))
|
||||||
|
}
|
@ -15,7 +15,7 @@ object MentionManagerUtilities {
|
|||||||
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
|
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
|
||||||
result.addAll(members)
|
result.addAll(members)
|
||||||
} else {
|
} else {
|
||||||
if (MentionsManager.shared.userPublicKeyCache[threadID] != null) { return }
|
if (MentionsManager.userPublicKeyCache[threadID] != null) { return }
|
||||||
val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context)
|
val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID))
|
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID))
|
||||||
var record: MessageRecord? = reader.next
|
var record: MessageRecord? = reader.next
|
||||||
@ -30,6 +30,6 @@ object MentionManagerUtilities {
|
|||||||
reader.close()
|
reader.close()
|
||||||
result.add(TextSecurePreferences.getLocalNumber(context)!!)
|
result.add(TextSecurePreferences.getLocalNumber(context)!!)
|
||||||
}
|
}
|
||||||
MentionsManager.shared.userPublicKeyCache[threadID] = result
|
MentionsManager.userPublicKeyCache[threadID] = result
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ import android.text.style.StyleSpan
|
|||||||
import android.util.Range
|
import android.util.Range
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import nl.komponents.kovenant.combine.Tuple2
|
import nl.komponents.kovenant.combine.Tuple2
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
@ -23,21 +24,22 @@ object MentionUtilities {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, threadID: Long, context: Context): SpannableString {
|
fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, threadID: Long, context: Context): SpannableString {
|
||||||
var text = text
|
var text = text
|
||||||
|
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||||
|
val isOpenGroup = threadDB.getRecipientForThreadId(threadID)?.isOpenGroupRecipient ?: false
|
||||||
val pattern = Pattern.compile("@[0-9a-fA-F]*")
|
val pattern = Pattern.compile("@[0-9a-fA-F]*")
|
||||||
var matcher = pattern.matcher(text)
|
var matcher = pattern.matcher(text)
|
||||||
val mentions = mutableListOf<Tuple2<Range<Int>, String>>()
|
val mentions = mutableListOf<Tuple2<Range<Int>, String>>()
|
||||||
var startIndex = 0
|
var startIndex = 0
|
||||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
||||||
if (matcher.find(startIndex)) {
|
if (matcher.find(startIndex)) {
|
||||||
while (true) {
|
while (true) {
|
||||||
val publicKey = text.subSequence(matcher.start() + 1, matcher.end()).toString() // +1 to get rid of the @
|
val publicKey = text.subSequence(matcher.start() + 1, matcher.end()).toString() // +1 to get rid of the @
|
||||||
val userDisplayName: String? = if (publicKey.toLowerCase() == userPublicKey.toLowerCase()) {
|
val userDisplayName: String? = if (publicKey.equals(userPublicKey, ignoreCase = true)) {
|
||||||
TextSecurePreferences.getProfileName(context)
|
TextSecurePreferences.getProfileName(context)
|
||||||
} else if (publicChat != null) {
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, publicKey)
|
|
||||||
} else {
|
} else {
|
||||||
DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey)
|
val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey)
|
||||||
|
val context = if (isOpenGroup) Contact.ContactContext.OPEN_GROUP else Contact.ContactContext.REGULAR
|
||||||
|
contact?.displayName(context)
|
||||||
}
|
}
|
||||||
if (userDisplayName != null) {
|
if (userDisplayName != null) {
|
||||||
text = text.subSequence(0, matcher.start()).toString() + "@" + userDisplayName + text.subSequence(matcher.end(), text.length)
|
text = text.subSequence(0, matcher.start()).toString() + "@" + userDisplayName + text.subSequence(matcher.end(), text.length)
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
@file:JvmName("NotificationUtilities")
|
|
||||||
package org.thoughtcrime.securesms.loki.utilities
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
|
||||||
|
|
||||||
fun getOpenGroupDisplayName(recipient: Recipient, threadRecipient: Recipient, context: Context): String {
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(threadRecipient)
|
|
||||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
|
||||||
val publicKey = recipient.address.toString()
|
|
||||||
val displayName = if (publicChat != null) {
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, publicKey)
|
|
||||||
} else {
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey)
|
|
||||||
}
|
|
||||||
return displayName ?: publicKey
|
|
||||||
}
|
|
@ -3,18 +3,10 @@ package org.thoughtcrime.securesms.loki.utilities
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
|
||||||
import org.session.libsession.utilities.ProfileKeyUtil
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
//TODO Refactor so methods declare specific type of checked exceptions and not generalized Exception.
|
//TODO Refactor so methods declare specific type of checked exceptions and not generalized Exception.
|
||||||
@ -28,23 +20,6 @@ object OpenGroupUtilities {
|
|||||||
*
|
*
|
||||||
* Consider using [org.thoughtcrime.securesms.loki.api.PublicChatInfoUpdateWorker] for lazy approach.
|
* Consider using [org.thoughtcrime.securesms.loki.api.PublicChatInfoUpdateWorker] for lazy approach.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@WorkerThread
|
|
||||||
@Throws(Exception::class)
|
|
||||||
fun updateGroupInfo(context: Context, url: String, channel: Long) {
|
|
||||||
// Check if open group has a related DB record.
|
|
||||||
val groupId = GroupUtil.getEncodedOpenGroupID(OpenGroup.getId(channel, url).toByteArray())
|
|
||||||
if (!DatabaseFactory.getGroupDatabase(context).hasGroup(groupId)) {
|
|
||||||
throw IllegalStateException("Attempt to update open group info for non-existent DB record: $groupId")
|
|
||||||
}
|
|
||||||
|
|
||||||
val info = OpenGroupAPI.getChannelInfo(channel, url).get()
|
|
||||||
|
|
||||||
OpenGroupAPI.updateProfileIfNeeded(channel, url, groupId, info, false)
|
|
||||||
|
|
||||||
EventBus.getDefault().post(GroupInfoUpdatedEvent(url, channel))
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
|
@ -2,13 +2,15 @@ package org.thoughtcrime.securesms.loki.views
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.text.TextUtils
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
|
||||||
@ -56,7 +58,7 @@ class ConversationView : LinearLayout {
|
|||||||
}
|
}
|
||||||
profilePictureView.glide = glide
|
profilePictureView.glide = glide
|
||||||
profilePictureView.update(thread.recipient, thread.threadId)
|
profilePictureView.update(thread.recipient, thread.threadId)
|
||||||
val senderDisplayName = if (thread.recipient.isLocalNumber) context.getString(R.string.note_to_self) else if (!thread.recipient.name.isNullOrEmpty()) thread.recipient.name else thread.recipient.address.toString()
|
val senderDisplayName = getUserDisplayName(thread.recipient) ?: thread.recipient.address.toString()
|
||||||
btnGroupNameDisplay.text = senderDisplayName
|
btnGroupNameDisplay.text = senderDisplayName
|
||||||
timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date)
|
timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date)
|
||||||
muteIndicatorImageView.visibility = if (thread.recipient.isMuted) VISIBLE else GONE
|
muteIndicatorImageView.visibility = if (thread.recipient.isMuted) VISIBLE else GONE
|
||||||
@ -85,9 +87,12 @@ class ConversationView : LinearLayout {
|
|||||||
profilePictureView.recycle()
|
profilePictureView.recycle()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getUserDisplayName(publicKey: String?): String? {
|
private fun getUserDisplayName(recipient: Recipient): String? {
|
||||||
if (TextUtils.isEmpty(publicKey)) return null
|
if (recipient.isLocalNumber) {
|
||||||
return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!)
|
return context.getString(R.string.note_to_self)
|
||||||
|
} else {
|
||||||
|
return recipient.name // Internally uses the Contact API
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
@ -17,10 +17,10 @@ class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defS
|
|||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.mentionCandidates = newValue }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.mentionCandidates = newValue }
|
||||||
var glide: GlideRequests? = null
|
var glide: GlideRequests? = null
|
||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.glide = newValue }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.glide = newValue }
|
||||||
var publicChatServer: String? = null
|
var openGroupServer: String? = null
|
||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.publicChatServer = publicChatServer }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.openGroupServer = openGroupServer }
|
||||||
var publicChatChannel: Long? = null
|
var openGroupRoom: String? = null
|
||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.publicChatChannel = publicChatChannel }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.openGroupRoom = openGroupRoom }
|
||||||
var onMentionCandidateSelected: ((Mention) -> Unit)? = null
|
var onMentionCandidateSelected: ((Mention) -> Unit)? = null
|
||||||
|
|
||||||
private val mentionCandidateSelectionViewAdapter by lazy { Adapter(context) }
|
private val mentionCandidateSelectionViewAdapter by lazy { Adapter(context) }
|
||||||
@ -29,8 +29,8 @@ class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defS
|
|||||||
var mentionCandidates = listOf<Mention>()
|
var mentionCandidates = listOf<Mention>()
|
||||||
set(newValue) { field = newValue; notifyDataSetChanged() }
|
set(newValue) { field = newValue; notifyDataSetChanged() }
|
||||||
var glide: GlideRequests? = null
|
var glide: GlideRequests? = null
|
||||||
var publicChatServer: String? = null
|
var openGroupServer: String? = null
|
||||||
var publicChatChannel: Long? = null
|
var openGroupRoom: String? = null
|
||||||
|
|
||||||
override fun getCount(): Int {
|
override fun getCount(): Int {
|
||||||
return mentionCandidates.count()
|
return mentionCandidates.count()
|
||||||
@ -49,8 +49,8 @@ class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defS
|
|||||||
val mentionCandidate = getItem(position)
|
val mentionCandidate = getItem(position)
|
||||||
cell.glide = glide
|
cell.glide = glide
|
||||||
cell.mentionCandidate = mentionCandidate
|
cell.mentionCandidate = mentionCandidate
|
||||||
cell.publicChatServer = publicChatServer
|
cell.openGroupServer = openGroupServer
|
||||||
cell.publicChatChannel = publicChatChannel
|
cell.openGroupRoom = openGroupRoom
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,10 +68,10 @@ class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defS
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun show(mentionCandidates: List<Mention>, threadID: Long) {
|
fun show(mentionCandidates: List<Mention>, threadID: Long) {
|
||||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
|
||||||
if (publicChat != null) {
|
if (openGroup != null) {
|
||||||
publicChatServer = publicChat.server
|
openGroupServer = openGroup.server
|
||||||
publicChatChannel = publicChat.channel
|
openGroupRoom = openGroup.room
|
||||||
}
|
}
|
||||||
this.mentionCandidates = mentionCandidates
|
this.mentionCandidates = mentionCandidates
|
||||||
val layoutParams = this.layoutParams as ViewGroup.LayoutParams
|
val layoutParams = this.layoutParams as ViewGroup.LayoutParams
|
||||||
|
@ -8,16 +8,16 @@ import android.view.ViewGroup
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.android.synthetic.main.view_mention_candidate.view.*
|
import kotlinx.android.synthetic.main.view_mention_candidate.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
|
||||||
import org.session.libsession.messaging.mentions.Mention
|
import org.session.libsession.messaging.mentions.Mention
|
||||||
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
|
|
||||||
class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
var mentionCandidate = Mention("", "")
|
var mentionCandidate = Mention("", "")
|
||||||
set(newValue) { field = newValue; update() }
|
set(newValue) { field = newValue; update() }
|
||||||
var glide: GlideRequests? = null
|
var glide: GlideRequests? = null
|
||||||
var publicChatServer: String? = null
|
var openGroupServer: String? = null
|
||||||
var publicChatChannel: Long? = null
|
var openGroupRoom: String? = null
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||||
constructor(context: Context) : this(context, null)
|
constructor(context: Context) : this(context, null)
|
||||||
@ -37,8 +37,8 @@ class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr:
|
|||||||
profilePictureView.isRSSFeed = false
|
profilePictureView.isRSSFeed = false
|
||||||
profilePictureView.glide = glide!!
|
profilePictureView.glide = glide!!
|
||||||
profilePictureView.update()
|
profilePictureView.update()
|
||||||
if (publicChatServer != null && publicChatChannel != null) {
|
if (openGroupServer != null && openGroupRoom != null) {
|
||||||
val isUserModerator = OpenGroupAPI.isUserModerator(mentionCandidate.publicKey, publicChatChannel!!, publicChatServer!!)
|
val isUserModerator = OpenGroupAPIV2.isUserModerator(mentionCandidate.publicKey, openGroupRoom!!, openGroupServer!!)
|
||||||
moderatorIconImageView.visibility = if (isUserModerator) View.VISIBLE else View.GONE
|
moderatorIconImageView.visibility = if (isUserModerator) View.VISIBLE else View.GONE
|
||||||
} else {
|
} else {
|
||||||
moderatorIconImageView.visibility = View.GONE
|
moderatorIconImageView.visibility = View.GONE
|
||||||
|
@ -11,6 +11,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|||||||
import kotlinx.android.synthetic.main.view_profile_picture.view.*
|
import kotlinx.android.synthetic.main.view_profile_picture.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.avatars.ProfileContactPhoto
|
import org.session.libsession.avatars.ProfileContactPhoto
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.messaging.mentions.MentionsManager
|
import org.session.libsession.messaging.mentions.MentionsManager
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
@ -29,7 +30,7 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
var additionalDisplayName: String? = null
|
var additionalDisplayName: String? = null
|
||||||
var isRSSFeed = false
|
var isRSSFeed = false
|
||||||
var isLarge = false
|
var isLarge = false
|
||||||
private val imagesCached = mutableSetOf<String>()
|
private val profilePicturesCached = mutableMapOf<String,String?>()
|
||||||
|
|
||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
constructor(context: Context) : super(context) {
|
constructor(context: Context) : super(context) {
|
||||||
@ -57,23 +58,15 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
fun update(recipient: Recipient, threadID: Long) {
|
fun update(recipient: Recipient, threadID: Long) {
|
||||||
fun getUserDisplayName(publicKey: String?): String? {
|
fun getUserDisplayName(publicKey: String): String {
|
||||||
if (publicKey == null || publicKey.isBlank()) {
|
val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey)
|
||||||
return null
|
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
|
||||||
} else {
|
|
||||||
var result = DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey)
|
|
||||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
|
||||||
if (result == null && publicChat != null) {
|
|
||||||
result = DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, publicKey)
|
|
||||||
}
|
|
||||||
return result ?: publicKey
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fun isOpenGroupWithProfilePicture(recipient: Recipient): Boolean {
|
fun isOpenGroupWithProfilePicture(recipient: Recipient): Boolean {
|
||||||
return recipient.isOpenGroupRecipient && recipient.groupAvatarId != null
|
return recipient.isOpenGroupRecipient && recipient.groupAvatarId != null
|
||||||
}
|
}
|
||||||
if (recipient.isGroupRecipient && !isOpenGroupWithProfilePicture(recipient)) {
|
if (recipient.isGroupRecipient && !isOpenGroupWithProfilePicture(recipient)) {
|
||||||
val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toMutableList() ?: mutableListOf()
|
val users = MentionsManager.userPublicKeyCache[threadID]?.toMutableList() ?: mutableListOf()
|
||||||
users.remove(TextSecurePreferences.getLocalNumber(context))
|
users.remove(TextSecurePreferences.getLocalNumber(context))
|
||||||
val randomUsers = users.sorted().toMutableList() // Sort to provide a level of stability
|
val randomUsers = users.sorted().toMutableList() // Sort to provide a level of stability
|
||||||
if (users.count() == 1) {
|
if (users.count() == 1) {
|
||||||
@ -90,7 +83,8 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
recipient.name == "Session Updates" ||
|
recipient.name == "Session Updates" ||
|
||||||
recipient.name == "Session Public Chat"
|
recipient.name == "Session Public Chat"
|
||||||
} else {
|
} else {
|
||||||
publicKey = recipient.address.toString()
|
val publicKey = recipient.address.toString()
|
||||||
|
this.publicKey = publicKey
|
||||||
displayName = getUserDisplayName(publicKey)
|
displayName = getUserDisplayName(publicKey)
|
||||||
additionalPublicKey = null
|
additionalPublicKey = null
|
||||||
isRSSFeed = false
|
isRSSFeed = false
|
||||||
@ -146,13 +140,13 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
private fun setProfilePictureIfNeeded(imageView: ImageView, publicKey: String, displayName: String?, @DimenRes sizeResId: Int) {
|
private fun setProfilePictureIfNeeded(imageView: ImageView, publicKey: String, displayName: String?, @DimenRes sizeResId: Int) {
|
||||||
if (publicKey.isNotEmpty()) {
|
if (publicKey.isNotEmpty()) {
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
||||||
if (imagesCached.contains(publicKey)) return
|
if (profilePicturesCached.containsKey(publicKey) && profilePicturesCached[publicKey] == recipient.profileAvatar) return
|
||||||
val signalProfilePicture = recipient.contactPhoto
|
val signalProfilePicture = recipient.contactPhoto
|
||||||
if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0"
|
val avatar = (signalProfilePicture as? ProfileContactPhoto)?.avatarObject
|
||||||
&& (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") {
|
if (signalProfilePicture != null && avatar != "0" && avatar != "") {
|
||||||
glide.clear(imageView)
|
glide.clear(imageView)
|
||||||
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).circleCrop().into(imageView)
|
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).circleCrop().into(imageView)
|
||||||
imagesCached.add(publicKey)
|
profilePicturesCached[publicKey] = recipient.profileAvatar
|
||||||
} else {
|
} else {
|
||||||
val sizeInPX = resources.getDimensionPixelSize(sizeResId)
|
val sizeInPX = resources.getDimensionPixelSize(sizeResId)
|
||||||
glide.clear(imageView)
|
glide.clear(imageView)
|
||||||
@ -162,7 +156,7 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
publicKey,
|
publicKey,
|
||||||
displayName
|
displayName
|
||||||
)).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
)).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
||||||
imagesCached.add(publicKey)
|
profilePicturesCached[publicKey] = recipient.profileAvatar
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageDrawable(null)
|
imageView.setImageDrawable(null)
|
||||||
@ -170,7 +164,7 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun recycle() {
|
fun recycle() {
|
||||||
imagesCached.clear()
|
profilePicturesCached.clear()
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import android.widget.LinearLayout
|
|||||||
import kotlinx.android.synthetic.main.view_conversation.view.profilePictureView
|
import kotlinx.android.synthetic.main.view_conversation.view.profilePictureView
|
||||||
import kotlinx.android.synthetic.main.view_user.view.*
|
import kotlinx.android.synthetic.main.view_user.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
@ -48,17 +49,9 @@ class UserView : LinearLayout {
|
|||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) {
|
fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) {
|
||||||
fun getUserDisplayName(publicKey: String?): String? {
|
fun getUserDisplayName(publicKey: String): String {
|
||||||
if (publicKey == null || publicKey.isBlank()) {
|
val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey)
|
||||||
return null
|
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
|
||||||
} else {
|
|
||||||
var result = DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey)
|
|
||||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(openGroupThreadID)
|
|
||||||
if (result == null && publicChat != null) {
|
|
||||||
result = DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, publicKey)
|
|
||||||
}
|
|
||||||
return result ?: publicKey
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(user)
|
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(user)
|
||||||
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadID, context) // FIXME: This is a bad place to do this
|
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadID, context) // FIXME: This is a bad place to do this
|
||||||
|
@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.session.libsession.messaging.file_server.FileServerAPI;
|
import org.session.libsession.messaging.file_server.FileServerAPIV2;
|
||||||
|
|
||||||
public class PushMediaConstraints extends MediaConstraints {
|
public class PushMediaConstraints extends MediaConstraints {
|
||||||
|
|
||||||
@ -21,26 +21,26 @@ public class PushMediaConstraints extends MediaConstraints {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getImageMaxSize(Context context) {
|
public int getImageMaxSize(Context context) {
|
||||||
return (int) (((double) FileServerAPI.Companion.getMaxFileSize()) / FileServerAPI.Companion.getFileSizeORMultiplier());
|
return (int) (((double) FileServerAPIV2.maxFileSize) / FileServerAPIV2.fileSizeORMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getGifMaxSize(Context context) {
|
public int getGifMaxSize(Context context) {
|
||||||
return (int) (((double) FileServerAPI.Companion.getMaxFileSize()) / FileServerAPI.Companion.getFileSizeORMultiplier());
|
return (int) (((double) FileServerAPIV2.maxFileSize) / FileServerAPIV2.fileSizeORMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVideoMaxSize(Context context) {
|
public int getVideoMaxSize(Context context) {
|
||||||
return (int) (((double) FileServerAPI.Companion.getMaxFileSize()) / FileServerAPI.Companion.getFileSizeORMultiplier());
|
return (int) (((double) FileServerAPIV2.maxFileSize) / FileServerAPIV2.fileSizeORMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAudioMaxSize(Context context) {
|
public int getAudioMaxSize(Context context) {
|
||||||
return (int) (((double) FileServerAPI.Companion.getMaxFileSize()) / FileServerAPI.Companion.getFileSizeORMultiplier());
|
return (int) (((double) FileServerAPIV2.maxFileSize) / FileServerAPIV2.fileSizeORMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDocumentMaxSize(Context context) {
|
public int getDocumentMaxSize(Context context) {
|
||||||
return (int) (((double) FileServerAPI.Companion.getMaxFileSize()) / FileServerAPI.Companion.getFileSizeORMultiplier());
|
return (int) (((double) FileServerAPIV2.maxFileSize) / FileServerAPIV2.fileSizeORMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,9 +287,6 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
|||||||
} finally {
|
} finally {
|
||||||
if (telcoCursor != null) telcoCursor.close();
|
if (telcoCursor != null) telcoCursor.close();
|
||||||
if (pushCursor != null) pushCursor.close();
|
if (pushCursor != null) pushCursor.close();
|
||||||
if (!OpenGroupManager.INSTANCE.isAllCaughtUp()) {
|
|
||||||
OpenGroupManager.INSTANCE.setAllCaughtUp(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,14 +8,14 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.NotificationUtilities;
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -49,8 +49,15 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
|
|||||||
|
|
||||||
public void setMostRecentSender(Recipient recipient, Recipient threadRecipient) {
|
public void setMostRecentSender(Recipient recipient, Recipient threadRecipient) {
|
||||||
String displayName = recipient.toShortString();
|
String displayName = recipient.toShortString();
|
||||||
if (threadRecipient.isGroupRecipient()) {
|
if (threadRecipient.isOpenGroupRecipient()) {
|
||||||
displayName = NotificationUtilities.getOpenGroupDisplayName(recipient, threadRecipient, context);
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(context);
|
||||||
|
String sessionID = recipient.getAddress().serialize();
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(sessionID);
|
||||||
|
if (contact != null) {
|
||||||
|
displayName = contact.displayName(Contact.ContactContext.OPEN_GROUP);
|
||||||
|
} else {
|
||||||
|
displayName = sessionID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (privacy.isDisplayContact()) {
|
if (privacy.isDisplayContact()) {
|
||||||
setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s, displayName));
|
setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s, displayName));
|
||||||
@ -71,8 +78,15 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
|
|||||||
|
|
||||||
public void addMessageBody(@NonNull Recipient sender, Recipient threadRecipient, @Nullable CharSequence body) {
|
public void addMessageBody(@NonNull Recipient sender, Recipient threadRecipient, @Nullable CharSequence body) {
|
||||||
String displayName = sender.toShortString();
|
String displayName = sender.toShortString();
|
||||||
if (threadRecipient.isGroupRecipient()) {
|
if (threadRecipient.isOpenGroupRecipient()) {
|
||||||
displayName = NotificationUtilities.getOpenGroupDisplayName(sender, threadRecipient, context);
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(context);
|
||||||
|
String sessionID = sender.getAddress().serialize();
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(sessionID);
|
||||||
|
if (contact != null) {
|
||||||
|
displayName = contact.displayName(Contact.ContactContext.OPEN_GROUP);
|
||||||
|
} else {
|
||||||
|
displayName = sessionID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (privacy.isDisplayMessage()) {
|
if (privacy.isDisplayMessage()) {
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||||
|
@ -10,6 +10,7 @@ import org.session.libsession.messaging.sending_receiving.notifications.MessageN
|
|||||||
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsession.utilities.Debouncer;
|
import org.session.libsession.utilities.Debouncer;
|
||||||
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.session.libsignal.utilities.ThreadUtils;
|
import org.session.libsignal.utilities.ThreadUtils;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
|
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
|
||||||
@ -23,7 +24,7 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
|||||||
@MainThread
|
@MainThread
|
||||||
public OptimizedMessageNotifier(@NonNull MessageNotifier wrapped) {
|
public OptimizedMessageNotifier(@NonNull MessageNotifier wrapped) {
|
||||||
this.wrapped = wrapped;
|
this.wrapped = wrapped;
|
||||||
this.debouncer = new Debouncer(TimeUnit.SECONDS.toMillis(1));
|
this.debouncer = new Debouncer(TimeUnit.SECONDS.toMillis(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,22 +15,21 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationCompat.Action;
|
import androidx.core.app.NotificationCompat.Action;
|
||||||
import androidx.core.app.RemoteInput;
|
import androidx.core.app.RemoteInput;
|
||||||
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.session.libsession.avatars.ContactColors;
|
import org.session.libsession.avatars.ContactColors;
|
||||||
import org.session.libsession.avatars.ContactPhoto;
|
import org.session.libsession.avatars.ContactPhoto;
|
||||||
import org.session.libsession.avatars.GeneratedContactPhoto;
|
import org.session.libsession.avatars.GeneratedContactPhoto;
|
||||||
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator;
|
import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.NotificationUtilities;
|
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
@ -40,11 +39,9 @@ import org.session.libsession.utilities.recipients.Recipient;
|
|||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
public class SingleRecipientNotificationBuilder extends AbstractNotificationBuilder {
|
public class SingleRecipientNotificationBuilder extends AbstractNotificationBuilder {
|
||||||
@ -121,8 +118,16 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
{
|
{
|
||||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
||||||
|
|
||||||
if (privacy.isDisplayContact() && threadRecipients.isGroupRecipient()) {
|
if (privacy.isDisplayContact() && threadRecipients.isOpenGroupRecipient()) {
|
||||||
String displayName = NotificationUtilities.getOpenGroupDisplayName(individualRecipient, threadRecipients, context);
|
String displayName;
|
||||||
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(context);
|
||||||
|
String sessionID = individualRecipient.getAddress().serialize();
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(sessionID);
|
||||||
|
if (contact != null) {
|
||||||
|
displayName = contact.displayName(Contact.ContactContext.OPEN_GROUP);
|
||||||
|
} else {
|
||||||
|
displayName = sessionID;
|
||||||
|
}
|
||||||
if (displayName != null) {
|
if (displayName != null) {
|
||||||
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
||||||
}
|
}
|
||||||
@ -209,8 +214,16 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
{
|
{
|
||||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
||||||
|
|
||||||
if (privacy.isDisplayContact() && threadRecipient.isGroupRecipient()) {
|
if (privacy.isDisplayContact() && threadRecipient.isOpenGroupRecipient()) {
|
||||||
String displayName = NotificationUtilities.getOpenGroupDisplayName(individualRecipient, threadRecipient, context);
|
String displayName;
|
||||||
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(context);
|
||||||
|
String sessionID = individualRecipient.getAddress().serialize();
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(sessionID);
|
||||||
|
if (contact != null) {
|
||||||
|
displayName = contact.displayName(Contact.ContactContext.OPEN_GROUP);
|
||||||
|
} else {
|
||||||
|
displayName = sessionID;
|
||||||
|
}
|
||||||
if (displayName != null) {
|
if (displayName != null) {
|
||||||
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,70 @@
|
|||||||
package org.thoughtcrime.securesms.sskenvironment
|
package org.thoughtcrime.securesms.sskenvironment
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.SSKEnvironment
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||||
|
|
||||||
class ProfileManager: SSKEnvironment.ProfileManagerProtocol {
|
class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
|
||||||
override fun setDisplayName(context: Context, recipient: Recipient, displayName: String) {
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setDisplayName(recipient.address.serialize(), displayName)
|
override fun setNickname(context: Context, recipient: Recipient, nickname: String?) {
|
||||||
|
val sessionID = recipient.address.serialize()
|
||||||
|
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
|
||||||
|
var contact = contactDatabase.getContactWithSessionID(sessionID)
|
||||||
|
if (contact == null) contact = Contact(sessionID)
|
||||||
|
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
|
||||||
|
if (contact.nickname != nickname) {
|
||||||
|
contact.nickname = nickname
|
||||||
|
contactDatabase.setContact(contact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setName(context: Context, recipient: Recipient, name: String) {
|
||||||
|
// New API
|
||||||
|
val sessionID = recipient.address.serialize()
|
||||||
|
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
|
||||||
|
var contact = contactDatabase.getContactWithSessionID(sessionID)
|
||||||
|
if (contact == null) contact = Contact(sessionID)
|
||||||
|
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
|
||||||
|
if (contact.name != name) {
|
||||||
|
contact.name = name
|
||||||
|
contactDatabase.setContact(contact)
|
||||||
|
}
|
||||||
|
// Old API
|
||||||
|
val database = DatabaseFactory.getRecipientDatabase(context)
|
||||||
|
database.setProfileName(recipient, name)
|
||||||
|
recipient.notifyListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
|
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
|
||||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(recipient, profilePictureURL))
|
val job = RetrieveProfileAvatarJob(recipient, profilePictureURL)
|
||||||
|
ApplicationContext.getInstance(context).jobManager.add(job)
|
||||||
|
val sessionID = recipient.address.serialize()
|
||||||
|
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
|
||||||
|
var contact = contactDatabase.getContactWithSessionID(sessionID)
|
||||||
|
if (contact == null) contact = Contact(sessionID)
|
||||||
|
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
|
||||||
|
if (contact.profilePictureURL != profilePictureURL) {
|
||||||
|
contact.profilePictureURL = profilePictureURL
|
||||||
|
contactDatabase.setContact(contact)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray) {
|
override fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray) {
|
||||||
|
// New API
|
||||||
|
val sessionID = recipient.address.serialize()
|
||||||
|
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
|
||||||
|
var contact = contactDatabase.getContactWithSessionID(sessionID)
|
||||||
|
if (contact == null) contact = Contact(sessionID)
|
||||||
|
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
|
||||||
|
if (!contact.profilePictureEncryptionKey.contentEquals(profileKey)) {
|
||||||
|
contact.profilePictureEncryptionKey = profileKey
|
||||||
|
contactDatabase.setContact(contact)
|
||||||
|
}
|
||||||
|
// Old API
|
||||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
val database = DatabaseFactory.getRecipientDatabase(context)
|
||||||
database.setProfileKey(recipient, profileKey)
|
database.setProfileKey(recipient, profileKey)
|
||||||
}
|
}
|
||||||
@ -25,8 +73,4 @@ class ProfileManager: SSKEnvironment.ProfileManagerProtocol {
|
|||||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
val database = DatabaseFactory.getRecipientDatabase(context)
|
||||||
database.setUnidentifiedAccessMode(recipient, unidentifiedAccessMode)
|
database.setUnidentifiedAccessMode(recipient, unidentifiedAccessMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateOpenGroupProfilePicturesIfNeeded(context: Context) {
|
|
||||||
ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -59,6 +59,6 @@
|
|||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:text="Link a Device" />
|
android:text="@string/activity_link_device_link_device" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -19,7 +19,7 @@
|
|||||||
android:textSize="@dimen/very_large_font_size"
|
android:textSize="@dimen/very_large_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Message Notifications" />
|
android:text="@string/activity_pn_mode_message_notifications" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -29,7 +29,7 @@
|
|||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="There are two ways Session can notify you of new messages." />
|
android:text="@string/activity_pn_mode_explanation" />
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.loki.views.PNModeView
|
<org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
android:id="@+id/fcmOptionView"
|
android:id="@+id/fcmOptionView"
|
||||||
@ -48,7 +48,7 @@
|
|||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Fast Mode" />
|
android:text="@string/activity_pn_mode_fast_mode" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="You’ll be notified of new messages reliably and immediately using Google’s notification servers." />
|
android:text="@string/activity_pn_mode_fast_mode_explanation" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -86,7 +86,7 @@
|
|||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Slow Mode" />
|
android:text="@string/activity_pn_mode_slow_mode" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -94,7 +94,7 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Session will occasionally check for new messages in the background." />
|
android:text="@string/activity_pn_mode_slow_mode_explanation" />
|
||||||
|
|
||||||
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -34,7 +35,7 @@
|
|||||||
style="@style/SessionEditText"
|
style="@style/SessionEditText"
|
||||||
android:id="@+id/mnemonicEditText"
|
android:id="@+id/mnemonicEditText"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="64dp"
|
||||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
@ -42,7 +43,7 @@
|
|||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
android:maxLines="2"
|
android:maxLines="3"
|
||||||
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
@ -69,6 +70,7 @@
|
|||||||
android:textColor="?android:textColorTertiary"
|
android:textColor="?android:textColorTertiary"
|
||||||
android:textColorLink="?colorAccent"
|
android:textColorLink="?colorAccent"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:text="By using this service, you agree to our Terms of Service and Privacy Policy" /> <!-- Intentionally not yet translated -->
|
android:text="By using this service, you agree to our Terms of Service and Privacy Policy"
|
||||||
|
tools:ignore="HardcodedText" /> <!-- Intentionally not yet translated -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -38,7 +39,7 @@
|
|||||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
android:layout_marginTop="@dimen/medium_spacing"
|
||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
tools:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -74,6 +75,7 @@
|
|||||||
android:textColor="?android:textColorTertiary"
|
android:textColor="?android:textColorTertiary"
|
||||||
android:textColorLink="?colorAccent"
|
android:textColorLink="?colorAccent"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:text="By using this service, you agree to our Terms of Service and Privacy Policy" /> <!-- Intentionally not yet translated -->
|
android:text="By using this service, you agree to our Terms of Service and Privacy Policy"
|
||||||
|
tools:ignore="HardcodedText" /> <!-- Intentionally not yet translated -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
@ -47,7 +47,7 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:text="nautical novelty populate onion awkward bent etiquette plant submarine itches vipers september axis maximum populate" />
|
tools:text="nautical novelty populate onion awkward bent etiquette plant submarine itches vipers september axis maximum populate" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/revealButton"
|
android:id="@+id/revealButton"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
android:textSize="@dimen/very_large_font_size"
|
android:textSize="@dimen/very_large_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Recovery Phrase" />
|
android:text="@string/fragment_recovery_phrase_title" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -28,13 +28,13 @@
|
|||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="To link your device, enter the recovery phrase that was given to you when you signed up." />
|
android:text="@string/activity_restore_explanation" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
style="@style/SessionEditText"
|
style="@style/SessionEditText"
|
||||||
android:id="@+id/mnemonicEditText"
|
android:id="@+id/mnemonicEditText"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="64dp"
|
||||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
@ -42,7 +42,7 @@
|
|||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
android:maxLines="2"
|
android:maxLines="3"
|
||||||
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="You're almost finished! 80%" />
|
android:text="@string/view_seed_reminder_title" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/subtitleTextView"
|
android:id="@+id/subtitleTextView"
|
||||||
@ -47,7 +47,7 @@
|
|||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:lines="2"
|
android:lines="2"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:text="Secure your account by saving your recovery phrase" />
|
android:text="@string/view_seed_reminder_subtitle_1" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -64,7 +64,7 @@
|
|||||||
android:layout_height="28dp"
|
android:layout_height="28dp"
|
||||||
android:layout_marginLeft="4dp"
|
android:layout_marginLeft="4dp"
|
||||||
android:textStyle="normal"
|
android:textStyle="normal"
|
||||||
android:text="Continue" />
|
android:text="@string/continue_2" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -99,7 +99,8 @@
|
|||||||
android:text="By using this service, you agree to our Terms of Service and Privacy Policy"
|
android:text="By using this service, you agree to our Terms of Service and Privacy Policy"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textColorLink="@color/text"
|
android:textColorLink="@color/text"
|
||||||
android:textSize="@dimen/very_small_font_size" /> <!-- Intentionally not yet translated -->
|
android:textSize="@dimen/very_small_font_size"
|
||||||
|
tools:ignore="HardcodedText" /> <!-- Intentionally not yet translated -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginLeft="64dp"
|
android:layout_marginLeft="64dp"
|
||||||
android:fontFamily="sans-serif-medium"
|
android:fontFamily="sans-serif-medium"
|
||||||
android:text="Session"
|
android:text="@string/app_name"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/very_large_font_size" />
|
android:textSize="@dimen/very_large_font_size" />
|
||||||
|
|
||||||
|
@ -59,6 +59,6 @@
|
|||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:text="Link a Device" />
|
android:text="@string/activity_link_device_link_device" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -18,7 +18,7 @@
|
|||||||
android:textSize="@dimen/large_font_size"
|
android:textSize="@dimen/large_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Community Guidelines" />
|
android:text="@string/ConversationActivity_open_group_guidelines" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/communityGuidelinesTextView"
|
android:id="@+id/communityGuidelinesTextView"
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
android:textSize="@dimen/large_font_size"
|
android:textSize="@dimen/large_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Message Notifications" />
|
android:text="@string/activity_pn_mode_message_notifications" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -29,7 +29,7 @@
|
|||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="There are two ways Session can notify you of new messages." />
|
android:text="@string/activity_pn_mode_explanation" />
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.loki.views.PNModeView
|
<org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
android:id="@+id/fcmOptionView"
|
android:id="@+id/fcmOptionView"
|
||||||
@ -48,7 +48,7 @@
|
|||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Fast Mode" />
|
android:text="@string/activity_pn_mode_fast_mode" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="You’ll be notified of new messages reliably and immediately using Google’s notification servers." />
|
android:text="@string/activity_pn_mode_fast_mode_explanation" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -86,7 +86,7 @@
|
|||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Slow Mode" />
|
android:text="@string/activity_pn_mode_slow_mode" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -94,7 +94,7 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Session will occasionally check for new messages in the background." />
|
android:text="@string/activity_pn_mode_slow_mode_explanation" />
|
||||||
|
|
||||||
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
||||||
|
|
||||||
@ -104,7 +104,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/medium_button_height"
|
android:layout_height="@dimen/medium_button_height"
|
||||||
android:layout_marginLeft="@dimen/massive_spacing"
|
android:layout_marginLeft="@dimen/massive_spacing"
|
||||||
android:layout_marginTop="@dimen/very_large_spacing"
|
android:layout_marginTop="20dp"
|
||||||
android:layout_marginRight="@dimen/massive_spacing"
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
android:layout_marginBottom="@dimen/onboarding_button_bottom_offset"
|
android:layout_marginBottom="@dimen/onboarding_button_bottom_offset"
|
||||||
android:text="@string/continue_2" />
|
android:text="@string/continue_2" />
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -34,7 +35,7 @@
|
|||||||
style="@style/SmallSessionEditText"
|
style="@style/SmallSessionEditText"
|
||||||
android:id="@+id/mnemonicEditText"
|
android:id="@+id/mnemonicEditText"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="64dp"
|
||||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
@ -42,7 +43,7 @@
|
|||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
android:maxLines="2"
|
android:maxLines="3"
|
||||||
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
@ -69,6 +70,7 @@
|
|||||||
android:textColorLink="@color/text"
|
android:textColorLink="@color/text"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="By using this service, you agree to our Terms of Service and Privacy Policy" /> <!-- Intentionally not yet translated -->
|
android:text="By using this service, you agree to our Terms of Service and Privacy Policy"
|
||||||
|
tools:ignore="HardcodedText" /> <!-- Intentionally not yet translated -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -35,11 +36,11 @@
|
|||||||
android:id="@+id/publicKeyTextView"
|
android:id="@+id/publicKeyTextView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="18dp"
|
android:textSize="18sp"
|
||||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
tools:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -75,6 +76,7 @@
|
|||||||
android:textColor="?android:textColorTertiary"
|
android:textColor="?android:textColorTertiary"
|
||||||
android:textColorLink="?colorAccent"
|
android:textColorLink="?colorAccent"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:text="By using this service, you agree to our Terms of Service and Privacy Policy" /> <!-- Intentionally not yet translated -->
|
android:text="By using this service, you agree to our Terms of Service and Privacy Policy"
|
||||||
|
tools:ignore="HardcodedText" /> <!-- Intentionally not yet translated -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
@ -47,7 +47,7 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:text="nautical novelty populate onion awkward bent etiquette plant submarine itches vipers september axis maximum populate" />
|
tools:text="nautical novelty populate onion awkward bent etiquette plant submarine itches vipers september axis maximum populate" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/revealButton"
|
android:id="@+id/revealButton"
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:fontFamily="@font/space_mono_regular"
|
android:fontFamily="@font/space_mono_regular"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
tools:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -211,7 +211,7 @@
|
|||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="Help us Translate Session" />
|
android:text="@string/activity_settings_help_translate_session" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/versionTextView"
|
android:id="@+id/versionTextView"
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="You don't have any contacts yet"
|
android:text="@string/fragment_contact_selection_empty_contacts"
|
||||||
android:textSize="@dimen/medium_font_size" />
|
android:textSize="@dimen/medium_font_size" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -55,9 +55,10 @@
|
|||||||
android:id="@+id/titleTextView"
|
android:id="@+id/titleTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@null"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:text="Conversation"
|
tools:text="Conversation"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/large_font_size"
|
android:textSize="@dimen/large_font_size"
|
||||||
android:fontFamily="sans-serif-medium" />
|
android:fontFamily="sans-serif-medium" />
|
||||||
@ -83,7 +84,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:text="26 members"
|
tools:text="26 members"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/small_font_size" />
|
android:textSize="@dimen/small_font_size" />
|
||||||
|
|
||||||
@ -217,7 +218,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:attr/windowBackground"
|
android:background="?android:attr/windowBackground"
|
||||||
android:paddingStart="5dip"
|
android:paddingStart="5dip"
|
||||||
android:text="160/160 (1)"
|
tools:text="160/160 (1)"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:background="@drawable/default_dialog_background_inset"
|
android:background="@drawable/default_dialog_background_inset"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@ -27,7 +27,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
android:layout_marginTop="@dimen/large_spacing"
|
||||||
android:padding="@dimen/small_spacing"
|
android:padding="@dimen/small_spacing"
|
||||||
android:text="habitat kiwi amply iceberg dog nerves spiderman soft match partial awakened maximum degrees"
|
tools:text="habitat kiwi amply iceberg dog nerves spiderman soft match partial awakened maximum degrees"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textAlignment="center" />
|
android:textAlignment="center" />
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/contentView"
|
android:id="@+id/contentView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -60,7 +60,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:fontFamily="@font/space_mono_regular"
|
android:fontFamily="@font/space_mono_regular"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
tools:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:padding="@dimen/large_spacing"
|
|
||||||
app:behavior_hideable="false"
|
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="64dp"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/ic_shield"
|
|
||||||
android:tint="?android:textColorPrimary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="Session IDs Just Got Better"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="We’ve upgraded Session IDs to make them even more private and secure. To ensure your continued privacy you're now required to upgrade."
|
|
||||||
android:textSize="@dimen/medium_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
|
||||||
android:text="Your existing contacts and conversations will be lost, but you’ll be able to use Session knowing you have the best privacy and security possible."
|
|
||||||
android:textSize="@dimen/medium_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Common.UnimportantOutline"
|
|
||||||
android:id="@+id/upgradeNowButton"
|
|
||||||
android:layout_width="240dp"
|
|
||||||
android:layout_height="@dimen/medium_button_height"
|
|
||||||
android:layout_marginTop="@dimen/very_large_spacing"
|
|
||||||
android:text="Upgrade Now" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Common.UnimportantOutline"
|
|
||||||
android:id="@+id/upgradeLaterButton"
|
|
||||||
android:layout_width="240dp"
|
|
||||||
android:layout_height="@dimen/medium_button_height"
|
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
|
||||||
android:text="Upgrade Later" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,61 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:padding="@dimen/large_spacing"
|
|
||||||
app:behavior_hideable="true"
|
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="64dp"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/ic_shield"
|
|
||||||
android:tint="?android:textColorPrimary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="Upgrade Successful!"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="Your new and improved Session ID is:"
|
|
||||||
android:textSize="@dimen/medium_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/SessionIDTextView"
|
|
||||||
android:id="@+id/sessionIDTextView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="18dp"
|
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
|
||||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Common.UnimportantOutline"
|
|
||||||
android:id="@+id/copyButton"
|
|
||||||
android:layout_width="240dp"
|
|
||||||
android:layout_height="@dimen/medium_button_height"
|
|
||||||
android:layout_marginTop="@dimen/very_large_spacing"
|
|
||||||
android:text="Copy" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Common.UnimportantOutline"
|
|
||||||
android:id="@+id/okButton"
|
|
||||||
android:layout_width="240dp"
|
|
||||||
android:layout_height="@dimen/medium_button_height"
|
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
|
||||||
android:text="@string/ok" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -18,7 +18,7 @@
|
|||||||
android:textSize="@dimen/large_font_size"
|
android:textSize="@dimen/large_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Recovery Phrase" />
|
android:text="@string/fragment_recovery_phrase_title" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -34,7 +34,7 @@
|
|||||||
style="@style/SmallSessionEditText"
|
style="@style/SmallSessionEditText"
|
||||||
android:id="@+id/mnemonicEditText"
|
android:id="@+id/mnemonicEditText"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="64dp"
|
||||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="@dimen/very_large_spacing"
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
@ -42,7 +42,7 @@
|
|||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
android:maxLines="2"
|
android:maxLines="3"
|
||||||
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:padding="@dimen/very_large_spacing"
|
android:padding="@dimen/very_large_spacing"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="Scan a user’s QR code to start a session. QR codes can be found by tapping the QR code icon in account settings."
|
android:text="@string/activity_create_private_chat_scan_qr_code_explanation"
|
||||||
android:background="?android:windowBackground"
|
android:background="?android:windowBackground"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textColor="?android:textColorTertiary" />
|
android:textColor="?android:textColorTertiary" />
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:paddingLeft="@dimen/large_spacing"
|
android:paddingLeft="@dimen/large_spacing"
|
||||||
@ -16,27 +16,97 @@
|
|||||||
android:id="@+id/profilePictureView"
|
android:id="@+id/profilePictureView"
|
||||||
android:layout_width="@dimen/large_profile_picture_size"
|
android:layout_width="@dimen/large_profile_picture_size"
|
||||||
android:layout_height="@dimen/large_profile_picture_size"
|
android:layout_height="@dimen/large_profile_picture_size"
|
||||||
android:layout_marginTop="@dimen/large_spacing" />
|
android:layout_marginTop="@dimen/large_spacing"/>
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/nameTextView"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
android:layout_marginTop="@dimen/medium_spacing"
|
||||||
android:textSize="@dimen/massive_font_size"
|
android:gravity="center">
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/text"
|
<LinearLayout
|
||||||
android:text="Spiderman" />
|
android:id="@+id/nameTextViewContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/nameTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginStart="@dimen/small_spacing"
|
||||||
|
android:layout_marginEnd="@dimen/small_spacing"
|
||||||
|
android:textSize="@dimen/large_font_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:text="Spiderman" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="22dp"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:src="@drawable/ic_baseline_edit_24" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/nameEditTextContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="invisible">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cancelNicknameEditingButton"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/ic_baseline_clear_24" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/nicknameEditText"
|
||||||
|
style="@style/SmallSessionEditText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginStart="@dimen/small_spacing"
|
||||||
|
android:layout_marginEnd="@dimen/small_spacing"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:inputType="text"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
|
android:hint="@string/fragment_user_details_bottom_sheet_edit_text_hint" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/saveNicknameButton"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/ic_baseline_done_24" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
style="@style/SessionIDTextView"
|
style="@style/SessionIDTextView"
|
||||||
android:id="@+id/publicKeyTextView"
|
android:id="@+id/publicKeyTextView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="@dimen/large_font_size"
|
android:layout_marginTop="@dimen/medium_spacing"
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
tools:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
style="@style/Widget.Session.Button.Common.ProminentOutline"
|
style="@style/Widget.Session.Button.Common.ProminentOutline"
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:text="Scan Me" />
|
android:text="@string/fragment_view_my_qr_code_title" />
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -59,7 +59,7 @@
|
|||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:text="This is your QR code. Other users can scan it to start a session with you." />
|
android:text="@string/fragment_view_my_qr_code_explanation" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
style="@style/Widget.Session.Button.Common.UnimportantOutline"
|
style="@style/Widget.Session.Button.Common.UnimportantOutline"
|
||||||
@ -68,7 +68,7 @@
|
|||||||
android:layout_height="@dimen/medium_button_height"
|
android:layout_height="@dimen/medium_button_height"
|
||||||
android:layout_marginTop="28dp"
|
android:layout_marginTop="28dp"
|
||||||
android:layout_marginBottom="@dimen/medium_spacing"
|
android:layout_marginBottom="@dimen/medium_spacing"
|
||||||
android:text="Share" />
|
android:text="@string/share" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
style="@style/Signal.Text.Body"
|
style="@style/Signal.Text.Body"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Session is Locked"
|
android:text="@string/activity_prompt_passphrase_session_locked"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textSize="@dimen/large_font_size"
|
android:textSize="@dimen/large_font_size"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
@ -73,7 +73,6 @@
|
|||||||
android:id="@+id/lock_screen_auth_container"
|
android:id="@+id/lock_screen_auth_container"
|
||||||
android:layout_width="196dp"
|
android:layout_width="196dp"
|
||||||
android:layout_height="@dimen/medium_button_height"
|
android:layout_height="@dimen/medium_button_height"
|
||||||
android:text="Tap to Unlock"/>
|
android:text="@string/activity_prompt_passphrase_tap_to_unlock"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
<TextView android:layout_width="wrap_content"
|
<TextView android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Share"
|
android:text="@string/share"
|
||||||
android:fontFamily="sans-serif-medium"
|
android:fontFamily="sans-serif-medium"
|
||||||
android:textSize="@dimen/very_large_font_size"
|
android:textSize="@dimen/very_large_font_size"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:alpha="0.4"
|
android:alpha="0.4"
|
||||||
android:text="9:41 AM" />
|
tools:text="9:41 AM" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Pinned message" />
|
android:text="@string/open_group_guidelines_pinned_message" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -42,7 +42,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:text="Community guidelines" />
|
android:text="@string/open_group_guidelines_community_guidelines" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -60,7 +60,7 @@
|
|||||||
android:layout_marginRight="12dp"
|
android:layout_marginRight="12dp"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textStyle="normal"
|
android:textStyle="normal"
|
||||||
android:text="Read" />
|
android:text="@string/open_group_guidelines_read" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="@dimen/small_font_size"
|
android:textSize="@dimen/small_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="You're almost finished! 80%" />
|
android:text="@string/view_seed_reminder_title" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/subtitleTextView"
|
android:id="@+id/subtitleTextView"
|
||||||
@ -47,7 +47,7 @@
|
|||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:lines="2"
|
android:lines="2"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:text="Secure your account by saving your recovery phrase" />
|
android:text="@string/view_seed_reminder_subtitle_1" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -64,7 +64,7 @@
|
|||||||
android:layout_height="28dp"
|
android:layout_height="28dp"
|
||||||
android:layout_marginLeft="4dp"
|
android:layout_marginLeft="4dp"
|
||||||
android:textStyle="normal"
|
android:textStyle="normal"
|
||||||
android:text="Continue" />
|
android:text="@string/continue_2" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_filter_search"
|
android:id="@+id/action_filter_search"
|
||||||
android:title=" "
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
app:showAsAction="collapseActionView|always"
|
||||||
app:showAsAction="collapseActionView|always" />
|
android:title="" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:title="Learn More"
|
android:title="@string/activity_path_learn_more_button_title"
|
||||||
android:id="@+id/learnMoreButton"
|
android:id="@+id/learnMoreButton"
|
||||||
android:icon="@drawable/ic_info_outline_white_24dp"
|
android:icon="@drawable/ic_info_outline_white_24dp"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
@ -62,6 +62,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Select contact info</string>
|
<string name="ConversationActivity_select_contact_info">Select contact info</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Sorry, there was an error setting your attachment.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Sorry, there was an error setting your attachment.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Invalid recipient!</string>
|
<string name="ConversationActivity_invalid_recipient">Invalid recipient!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Added to home screen</string>
|
<string name="ConversationActivity_added_to_home_screen">Added to home screen</string>
|
||||||
<string name="ConversationActivity_leave_group">Leave group?</string>
|
<string name="ConversationActivity_leave_group">Leave group?</string>
|
||||||
@ -354,6 +358,9 @@
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Audio</string>
|
<string name="QuoteView_audio">Audio</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -584,6 +591,7 @@
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -627,6 +635,7 @@
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -643,11 +652,13 @@
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -674,7 +685,18 @@
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -62,6 +62,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Əlaqə məlumatını seç</string>
|
<string name="ConversationActivity_select_contact_info">Əlaqə məlumatını seç</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Üzr istəyirik, faylın yüklənməsində xəta baş verdi.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Üzr istəyirik, faylın yüklənməsində xəta baş verdi.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Səhv qəbul edən!</string>
|
<string name="ConversationActivity_invalid_recipient">Səhv qəbul edən!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Baş səhifəyə əlavə edildi</string>
|
<string name="ConversationActivity_added_to_home_screen">Baş səhifəyə əlavə edildi</string>
|
||||||
<string name="ConversationActivity_leave_group">Qrupdan çıxırsan?</string>
|
<string name="ConversationActivity_leave_group">Qrupdan çıxırsan?</string>
|
||||||
@ -354,6 +358,9 @@
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Səs</string>
|
<string name="QuoteView_audio">Səs</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -584,6 +591,7 @@
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -627,6 +635,7 @@
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -643,11 +652,13 @@
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -674,7 +685,18 @@
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -62,6 +62,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Pilih info kontak</string>
|
<string name="ConversationActivity_select_contact_info">Pilih info kontak</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Maaf, terjadi kesalahan pada pengaturan lampiran anda.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Maaf, terjadi kesalahan pada pengaturan lampiran anda.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Penerima tidak lengkap!</string>
|
<string name="ConversationActivity_invalid_recipient">Penerima tidak lengkap!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Tambahkan ke layar utama</string>
|
<string name="ConversationActivity_added_to_home_screen">Tambahkan ke layar utama</string>
|
||||||
<string name="ConversationActivity_leave_group">Tinggalkan grup?</string>
|
<string name="ConversationActivity_leave_group">Tinggalkan grup?</string>
|
||||||
@ -352,6 +356,9 @@ memproses pertukaran kunci korupsi.</string>
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Audio</string>
|
<string name="QuoteView_audio">Audio</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -582,6 +589,7 @@ memproses pertukaran kunci korupsi.</string>
|
|||||||
<string name="activity_seed_title_2">Inilah kata pemulihan anda</string>
|
<string name="activity_seed_title_2">Inilah kata pemulihan anda</string>
|
||||||
<string name="activity_seed_explanation">Kata pemulihan adalah kunci Session ID -- bisa digunakan untuk mengembalikan Session ID ketika anda kehilangan perangkat. Simpan kata pemulihan di tempat yang aman dan jangan berikan kepada siapapun</string>
|
<string name="activity_seed_explanation">Kata pemulihan adalah kunci Session ID -- bisa digunakan untuk mengembalikan Session ID ketika anda kehilangan perangkat. Simpan kata pemulihan di tempat yang aman dan jangan berikan kepada siapapun</string>
|
||||||
<string name="activity_seed_reveal_button_title">Tekan untuk melihat</string>
|
<string name="activity_seed_reveal_button_title">Tekan untuk melihat</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Amankan akun anda dengan menyimpan kata pemulihan</string>
|
<string name="view_seed_reminder_subtitle_1">Amankan akun anda dengan menyimpan kata pemulihan</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Ketuk dan tekan kata yang disensor untuk mengetahui kata pemulihan anda, lalu simpan baik-baik untuk mengamnkan Session ID anda</string>
|
<string name="view_seed_reminder_subtitle_2">Ketuk dan tekan kata yang disensor untuk mengetahui kata pemulihan anda, lalu simpan baik-baik untuk mengamnkan Session ID anda</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Pastikan untuk menyimpan kata pemulihan di tempat yang aman</string>
|
<string name="view_seed_reminder_subtitle_3">Pastikan untuk menyimpan kata pemulihan di tempat yang aman</string>
|
||||||
@ -625,6 +633,7 @@ memproses pertukaran kunci korupsi.</string>
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Kata pemulihan</string>
|
<string name="activity_settings_recovery_phrase_button_title">Kata pemulihan</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Hapus data</string>
|
<string name="activity_settings_clear_all_data_button_title">Hapus data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifikasi</string>
|
<string name="activity_notification_settings_title">Notifikasi</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Gaya notifikasi</string>
|
<string name="activity_notification_settings_style_section_title">Gaya notifikasi</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Isi notifikasi</string>
|
<string name="activity_notification_settings_content_section_title">Isi notifikasi</string>
|
||||||
@ -641,11 +650,13 @@ memproses pertukaran kunci korupsi.</string>
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">Lihat kode QR saya</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">Lihat kode QR saya</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Pindai kode QR</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Pindai kode QR</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Pindai kode QR pengguna lain untuk memulai percakapan</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Pindai kode QR pengguna lain untuk memulai percakapan</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">Ini adalah kode QR anda. Pengguna lain bisa memindainya untuk memulai percakapan dengan anda</string>
|
<string name="fragment_view_my_qr_code_explanation">Ini adalah kode QR anda. Pengguna lain bisa memindainya untuk memulai percakapan dengan anda</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Bagikan kode QR</string>
|
<string name="fragment_view_my_qr_code_share_title">Bagikan kode QR</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Kontak</string>
|
<string name="fragment_contact_selection_contacts_title">Kontak</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Grup tertutup</string>
|
<string name="fragment_contact_selection_closed_groups_title">Grup tertutup</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Grup terbuka</string>
|
<string name="fragment_contact_selection_open_groups_title">Grup terbuka</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -672,7 +683,18 @@ memproses pertukaran kunci korupsi.</string>
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -66,6 +66,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Select contact info</string>
|
<string name="ConversationActivity_select_contact_info">Select contact info</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Sorry, there was an error setting your attachment.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Sorry, there was an error setting your attachment.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Invalid recipient!</string>
|
<string name="ConversationActivity_invalid_recipient">Invalid recipient!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Added to home screen</string>
|
<string name="ConversationActivity_added_to_home_screen">Added to home screen</string>
|
||||||
<string name="ConversationActivity_leave_group">Leave group?</string>
|
<string name="ConversationActivity_leave_group">Leave group?</string>
|
||||||
@ -380,6 +384,9 @@
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Audio</string>
|
<string name="QuoteView_audio">Audio</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -612,6 +619,7 @@
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -655,6 +663,7 @@
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -671,11 +680,13 @@
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -702,7 +713,18 @@
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -62,6 +62,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Seleccioneu informació del contacte</string>
|
<string name="ConversationActivity_select_contact_info">Seleccioneu informació del contacte</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">S\'ha produït un error en afegir el fitxer adjunt.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">S\'ha produït un error en afegir el fitxer adjunt.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Destinatari no vàlid.</string>
|
<string name="ConversationActivity_invalid_recipient">Destinatari no vàlid.</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">S\'ha afegit a la pantalla d\'inici.</string>
|
<string name="ConversationActivity_added_to_home_screen">S\'ha afegit a la pantalla d\'inici.</string>
|
||||||
<string name="ConversationActivity_leave_group">Voleu abandonar el grup?</string>
|
<string name="ConversationActivity_leave_group">Voleu abandonar el grup?</string>
|
||||||
@ -352,6 +356,9 @@ d\'intercanvi de claus!</string>
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Àudio</string>
|
<string name="QuoteView_audio">Àudio</string>
|
||||||
<string name="QuoteView_video">Vídeo</string>
|
<string name="QuoteView_video">Vídeo</string>
|
||||||
@ -582,6 +589,7 @@ d\'intercanvi de claus!</string>
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -625,6 +633,7 @@ d\'intercanvi de claus!</string>
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -641,11 +650,13 @@ d\'intercanvi de claus!</string>
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -672,7 +683,18 @@ d\'intercanvi de claus!</string>
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -66,6 +66,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Vybrat informace o kontaktu</string>
|
<string name="ConversationActivity_select_contact_info">Vybrat informace o kontaktu</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Omlouváme se, ale došlo k chybě při zpracování přílohy</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Omlouváme se, ale došlo k chybě při zpracování přílohy</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Chybný příjemce!</string>
|
<string name="ConversationActivity_invalid_recipient">Chybný příjemce!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Přidáno na plochu</string>
|
<string name="ConversationActivity_added_to_home_screen">Přidáno na plochu</string>
|
||||||
<string name="ConversationActivity_leave_group">Opustit skupinu?</string>
|
<string name="ConversationActivity_leave_group">Opustit skupinu?</string>
|
||||||
@ -377,6 +381,9 @@
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Audio</string>
|
<string name="QuoteView_audio">Audio</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -609,6 +616,7 @@
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -652,6 +660,7 @@
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -668,11 +677,13 @@
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -699,7 +710,18 @@
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -70,6 +70,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Dewis manylion cyswllt</string>
|
<string name="ConversationActivity_select_contact_info">Dewis manylion cyswllt</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Mae\'n ddrwg gennym, bu gwall wrth osod eich atodiad.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Mae\'n ddrwg gennym, bu gwall wrth osod eich atodiad.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Derbynnydd annilys!</string>
|
<string name="ConversationActivity_invalid_recipient">Derbynnydd annilys!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Ychwanegwyd at y sgrin gartref</string>
|
<string name="ConversationActivity_added_to_home_screen">Ychwanegwyd at y sgrin gartref</string>
|
||||||
<string name="ConversationActivity_leave_group">Gadael y grŵp</string>
|
<string name="ConversationActivity_leave_group">Gadael y grŵp</string>
|
||||||
@ -404,6 +408,9 @@
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Sain</string>
|
<string name="QuoteView_audio">Sain</string>
|
||||||
<string name="QuoteView_video">Fideo</string>
|
<string name="QuoteView_video">Fideo</string>
|
||||||
@ -638,6 +645,7 @@
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -681,6 +689,7 @@
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -697,11 +706,13 @@
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -728,7 +739,18 @@
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -62,6 +62,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Vælg kontaktinformation</string>
|
<string name="ConversationActivity_select_contact_info">Vælg kontaktinformation</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Beklager, der opstod en fejl ved vedhæftning af fil</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Beklager, der opstod en fejl ved vedhæftning af fil</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Ugyldig modtager!</string>
|
<string name="ConversationActivity_invalid_recipient">Ugyldig modtager!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Føjet til startskærm</string>
|
<string name="ConversationActivity_added_to_home_screen">Føjet til startskærm</string>
|
||||||
<string name="ConversationActivity_leave_group">Forlad gruppe?</string>
|
<string name="ConversationActivity_leave_group">Forlad gruppe?</string>
|
||||||
@ -352,6 +356,9 @@ udveksel besked!</string>
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Lyd</string>
|
<string name="QuoteView_audio">Lyd</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -582,6 +589,7 @@ udveksel besked!</string>
|
|||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
||||||
@ -625,6 +633,7 @@ udveksel besked!</string>
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_notification_settings_title">Notifications</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
||||||
@ -641,11 +650,13 @@ udveksel besked!</string>
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -672,7 +683,18 @@ udveksel besked!</string>
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -62,6 +62,10 @@
|
|||||||
<string name="ConversationActivity_select_contact_info">Kontaktinfo wählen</string>
|
<string name="ConversationActivity_select_contact_info">Kontaktinfo wählen</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Leider ist ein Fehler beim Hinzufügen des Anhangs aufgetreten.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Leider ist ein Fehler beim Hinzufügen des Anhangs aufgetreten.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Message</string>
|
||||||
|
<string name="ConversationActivity_compose">Compose</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Muted until %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d members</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Community Guidelines</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Ungültiger Kontakt!</string>
|
<string name="ConversationActivity_invalid_recipient">Ungültiger Kontakt!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Zum Startbildschirm hinzugefügt</string>
|
<string name="ConversationActivity_added_to_home_screen">Zum Startbildschirm hinzugefügt</string>
|
||||||
<string name="ConversationActivity_leave_group">Gruppe verlassen?</string>
|
<string name="ConversationActivity_leave_group">Gruppe verlassen?</string>
|
||||||
@ -351,6 +355,9 @@
|
|||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Pinned message</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Community guidelines</string>
|
||||||
|
<string name="open_group_guidelines_read">Read</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Audio</string>
|
<string name="QuoteView_audio">Audio</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
@ -581,6 +588,7 @@
|
|||||||
<string name="activity_seed_title_2">Das ist Ihr Wiederherstellungssatz.</string>
|
<string name="activity_seed_title_2">Das ist Ihr Wiederherstellungssatz.</string>
|
||||||
<string name="activity_seed_explanation">Ihr Wiederherstellungssatz ist der Hauptschlüssel für Ihre Session ID. Mit diesem Satz können Sie Ihre Session ID wiederherstellen, wenn Sie den Zugriff auf Ihr Gerät verlieren. Bewahren Sie Ihren Wiederherstellungssatz an einem sicheren Ort auf und geben Sie ihn an niemandem weiter.</string>
|
<string name="activity_seed_explanation">Ihr Wiederherstellungssatz ist der Hauptschlüssel für Ihre Session ID. Mit diesem Satz können Sie Ihre Session ID wiederherstellen, wenn Sie den Zugriff auf Ihr Gerät verlieren. Bewahren Sie Ihren Wiederherstellungssatz an einem sicheren Ort auf und geben Sie ihn an niemandem weiter.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Zur Anzeige gedrückt halten</string>
|
<string name="activity_seed_reveal_button_title">Zur Anzeige gedrückt halten</string>
|
||||||
|
<string name="view_seed_reminder_title">You\'re almost finished! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Sichern Sie Ihr Konto, indem Sie Ihren Wiederherstellungssatz speichern</string>
|
<string name="view_seed_reminder_subtitle_1">Sichern Sie Ihr Konto, indem Sie Ihren Wiederherstellungssatz speichern</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tippen und halten Sie die verborgenen Wörter, um Ihren Wiederherstellungssatz anzuzeigen, und speichern Sie ihn dann sicher, um Ihre Session ID zu sichern.</string>
|
<string name="view_seed_reminder_subtitle_2">Tippen und halten Sie die verborgenen Wörter, um Ihren Wiederherstellungssatz anzuzeigen, und speichern Sie ihn dann sicher, um Ihre Session ID zu sichern.</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Bewahren Sie Ihren Wiederherstellungssatz an einem sicheren Ort auf.</string>
|
<string name="view_seed_reminder_subtitle_3">Bewahren Sie Ihren Wiederherstellungssatz an einem sicheren Ort auf.</string>
|
||||||
@ -624,6 +632,7 @@
|
|||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_invite_button_title">Invite</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Wiederherstellungssatz</string>
|
<string name="activity_settings_recovery_phrase_button_title">Wiederherstellungssatz</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Daten löschen</string>
|
<string name="activity_settings_clear_all_data_button_title">Daten löschen</string>
|
||||||
|
<string name="activity_settings_help_translate_session">Help us Translate Session</string>
|
||||||
<string name="activity_notification_settings_title">Benachrichtigungen</string>
|
<string name="activity_notification_settings_title">Benachrichtigungen</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Stil der Benachrichtigungen</string>
|
<string name="activity_notification_settings_style_section_title">Stil der Benachrichtigungen</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Inhalt der Benachrichtigungen</string>
|
<string name="activity_notification_settings_content_section_title">Inhalt der Benachrichtigungen</string>
|
||||||
@ -640,11 +649,13 @@
|
|||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">Meinen QR-Code anzeigen</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">Meinen QR-Code anzeigen</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">QR-Code scannen</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">QR-Code scannen</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scannen Sie den QR-Code einer Person, um ein Gespräch mit ihr zu beginnen.</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Scannen Sie den QR-Code einer Person, um ein Gespräch mit ihr zu beginnen.</string>
|
||||||
|
<string name="fragment_view_my_qr_code_title">Scan Me</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">Das ist Ihr QR-Code. Andere Benutzer können ihn scannen, um eine Session mit Ihnen zu starten.</string>
|
<string name="fragment_view_my_qr_code_explanation">Das ist Ihr QR-Code. Andere Benutzer können ihn scannen, um eine Session mit Ihnen zu starten.</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">QR-Code freigeben</string>
|
<string name="fragment_view_my_qr_code_share_title">QR-Code freigeben</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Kontakte</string>
|
<string name="fragment_contact_selection_contacts_title">Kontakte</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Geschlossene Gruppen</string>
|
<string name="fragment_contact_selection_closed_groups_title">Geschlossene Gruppen</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Gruppen öffnen</string>
|
<string name="fragment_contact_selection_open_groups_title">Gruppen öffnen</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">You don\'t have any contacts yet</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Apply</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Done</string>
|
||||||
@ -671,7 +682,18 @@
|
|||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Select a file</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
||||||
<!-- LinkDeviceActivity -->
|
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
||||||
|
<string name="activity_link_device_link_device">Link a Device</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Message Notifications</string>
|
||||||
|
<string name="activity_pn_mode_explanation">There are two ways Session can notify you of new messages.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Fast Mode</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Slow Mode</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">You’ll be notified of new messages reliably and immediately using Google’s notification servers.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Session will occasionally check for new messages in the background.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Recovery Phrase</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Session is Locked</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Tap to Unlock</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
<string name="yes">Ναι</string>
|
<string name="yes">Ναι</string>
|
||||||
<string name="no">Όχι</string>
|
<string name="no">Όχι</string>
|
||||||
<string name="delete">Διαγραφή</string>
|
<string name="delete">Διαγραφή</string>
|
||||||
<string name="ban">Ban</string>
|
<string name="ban">Αποκλεισμός</string>
|
||||||
<string name="please_wait">Παρακαλώ περιμένετε...</string>
|
<string name="please_wait">Παρακαλώ περιμένετε...</string>
|
||||||
<string name="save">Αποθήκευση</string>
|
<string name="save">Αποθήκευση</string>
|
||||||
<string name="note_to_self">Να μην ξεχάσω </string>
|
<string name="note_to_self">Να μην ξεχάσω </string>
|
||||||
<string name="version_s">Version %s</string>
|
<string name="version_s">Έκδοση %s</string>
|
||||||
<!-- AbstractNotificationBuilder -->
|
<!-- AbstractNotificationBuilder -->
|
||||||
<string name="AbstractNotificationBuilder_new_message">Νέο μήνυμα</string>
|
<string name="AbstractNotificationBuilder_new_message">Νέο μήνυμα</string>
|
||||||
<!-- AlbumThumbnailView -->
|
<!-- AlbumThumbnailView -->
|
||||||
@ -61,7 +61,11 @@
|
|||||||
<string name="ConversationActivity_add_attachment">Προσθήκη συνημμένου</string>
|
<string name="ConversationActivity_add_attachment">Προσθήκη συνημμένου</string>
|
||||||
<string name="ConversationActivity_select_contact_info">Επιλογή πληροφοριών επαφής</string>
|
<string name="ConversationActivity_select_contact_info">Επιλογή πληροφοριών επαφής</string>
|
||||||
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Συγγνώμη, υπήρξε πρόβλημα με τη σύναψη αρχείου.</string>
|
<string name="ConversationActivity_sorry_there_was_an_error_setting_your_attachment">Συγγνώμη, υπήρξε πρόβλημα με τη σύναψη αρχείου.</string>
|
||||||
<string name="ConversationActivity_message">Message</string>
|
<string name="ConversationActivity_message">Μήνυμα</string>
|
||||||
|
<string name="ConversationActivity_compose">Δημιουργία</string>
|
||||||
|
<string name="ConversationActivity_muted_until_date">Σε σίγαση μέχρι %1$s</string>
|
||||||
|
<string name="ConversationActivity_member_count">%1$d μέλη</string>
|
||||||
|
<string name="ConversationActivity_open_group_guidelines">Οδηγίες Κοινότητας</string>
|
||||||
<string name="ConversationActivity_invalid_recipient">Μη έγκυρος/η παραλήπτης/τρια!</string>
|
<string name="ConversationActivity_invalid_recipient">Μη έγκυρος/η παραλήπτης/τρια!</string>
|
||||||
<string name="ConversationActivity_added_to_home_screen">Προστέθηκε στην κεντρική οθόνη</string>
|
<string name="ConversationActivity_added_to_home_screen">Προστέθηκε στην κεντρική οθόνη</string>
|
||||||
<string name="ConversationActivity_leave_group">Αποχώρηση από την ομάδα;</string>
|
<string name="ConversationActivity_leave_group">Αποχώρηση από την ομάδα;</string>
|
||||||
@ -73,15 +77,15 @@
|
|||||||
<string name="ConversationActivity_attachment_exceeds_size_limits">Το συνημμένο υπερβαίνει τα όρια μεγέθους για το είδος μηνύματος που στέλνετε.</string>
|
<string name="ConversationActivity_attachment_exceeds_size_limits">Το συνημμένο υπερβαίνει τα όρια μεγέθους για το είδος μηνύματος που στέλνετε.</string>
|
||||||
<string name="ConversationActivity_unable_to_record_audio">Η ηχογράφηση απέτυχε!</string>
|
<string name="ConversationActivity_unable_to_record_audio">Η ηχογράφηση απέτυχε!</string>
|
||||||
<string name="ConversationActivity_there_is_no_app_available_to_handle_this_link_on_your_device">Δεν υπάρχει διαθέσιμη εφαρμογή στην συσκευή σας να μπορεί να διαχειριστεί αυτό τον σύνδεσμο.</string>
|
<string name="ConversationActivity_there_is_no_app_available_to_handle_this_link_on_your_device">Δεν υπάρχει διαθέσιμη εφαρμογή στην συσκευή σας να μπορεί να διαχειριστεί αυτό τον σύνδεσμο.</string>
|
||||||
<string name="ConversationActivity_invite_to_open_group">Add members</string>
|
<string name="ConversationActivity_invite_to_open_group">Προσθέστε μέλη</string>
|
||||||
<string name="ConversationActivity_join_open_group">Join %s</string>
|
<string name="ConversationActivity_join_open_group">Εγγραφή %s</string>
|
||||||
<string name="ConversationActivity_join_open_group_confirmation_message">Are you sure you want to join the <b>%s</b> open group?</string>
|
<string name="ConversationActivity_join_open_group_confirmation_message">Είστε σίγουροι ότι θέλετε να συμμετάσχετε στην ανοιχτή ομάδα <b>%s</b>;</string>
|
||||||
<string name="ConversationActivity_to_send_audio_messages_allow_signal_access_to_your_microphone">Για να στείλετε μηνύματα ήχου, δώστε στο Session πρόσβαση στο μικρόφωνό σας.</string>
|
<string name="ConversationActivity_to_send_audio_messages_allow_signal_access_to_your_microphone">Για να στείλετε μηνύματα ήχου, δώστε στο Session πρόσβαση στο μικρόφωνό σας.</string>
|
||||||
<string name="ConversationActivity_signal_requires_the_microphone_permission_in_order_to_send_audio_messages">Το Session χρειάζεται τα δικαιώματα Μικροφώνου για να μπορούμε να στείλουμε μηνύματα ήχου, αλλά αυτά δεν έχουν δοθεί μόνιμα. Παρακαλώ πηγαίνετε στις ρυθμίσεις εφαρμογών, επιλέξτε τα \"Δικαιώματα\", και ενεργοποιήστε το \"Μικρόφωνο\".</string>
|
<string name="ConversationActivity_signal_requires_the_microphone_permission_in_order_to_send_audio_messages">Το Session χρειάζεται τα δικαιώματα Μικροφώνου για να μπορούμε να στείλουμε μηνύματα ήχου, αλλά αυτά δεν έχουν δοθεί μόνιμα. Παρακαλώ πηγαίνετε στις ρυθμίσεις εφαρμογών, επιλέξτε τα \"Δικαιώματα\", και ενεργοποιήστε το \"Μικρόφωνο\".</string>
|
||||||
<string name="ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera">Για να τραβήξετε φωτογραφίες και βίντεο, δώστε στο Session πρόσβαση στην κάμερα.</string>
|
<string name="ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera">Για να τραβήξετε φωτογραφίες και βίντεο, δώστε στο Session πρόσβαση στην κάμερα.</string>
|
||||||
<string name="ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video">Το Session χρειάζεται τα δικαιώματα Κάμερας για να μπορούμε να τραβήξουμε φωτογραφίες και βίντεο, αλλά αυτά δεν έχουν δοθεί μόνιμα. Παρακαλώ πηγαίνετε στις ρυθμίσεις εφαρμογών, επιλέξτε τα \"Δικαιώματα\", και ενεργοποιήστε την \"Κάμερα\".</string>
|
<string name="ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video">Το Session χρειάζεται τα δικαιώματα Κάμερας για να μπορούμε να τραβήξουμε φωτογραφίες και βίντεο, αλλά αυτά δεν έχουν δοθεί μόνιμα. Παρακαλώ πηγαίνετε στις ρυθμίσεις εφαρμογών, επιλέξτε τα \"Δικαιώματα\", και ενεργοποιήστε την \"Κάμερα\".</string>
|
||||||
<string name="ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video">Το Session χρειάζεται τα δικαιώματα Κάμερας για να τραβήξει φωτογραφίες ή βίντεο</string>
|
<string name="ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video">Το Session χρειάζεται τα δικαιώματα Κάμερας για να τραβήξει φωτογραφίες ή βίντεο</string>
|
||||||
<string name="ConversationActivity_quoted_contact_message">%1$s %2$s</string>
|
<string name="ConversationActivity_quoted_contact_message">%1$s, %2$s</string>
|
||||||
<string name="ConversationActivity_search_position">%1$dαπό%2$d</string>
|
<string name="ConversationActivity_search_position">%1$dαπό%2$d</string>
|
||||||
<string name="ConversationActivity_no_results">Δεν υπάρχουν αποτελέσματα</string>
|
<string name="ConversationActivity_no_results">Δεν υπάρχουν αποτελέσματα</string>
|
||||||
<!-- ConversationAdapter -->
|
<!-- ConversationAdapter -->
|
||||||
@ -98,7 +102,7 @@
|
|||||||
<item quantity="one">Αυτό θα διαγράψει οριστικά το επιλεγμένο μήνυμα.</item>
|
<item quantity="one">Αυτό θα διαγράψει οριστικά το επιλεγμένο μήνυμα.</item>
|
||||||
<item quantity="other">Αυτό θα διαγράψει οριστικά όλα τα %1$d επιλεγμένα μηνύματα.</item>
|
<item quantity="other">Αυτό θα διαγράψει οριστικά όλα τα %1$d επιλεγμένα μηνύματα.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="ConversationFragment_ban_selected_user">Ban this user?</string>
|
<string name="ConversationFragment_ban_selected_user">Αποκλεισμός αυτού του χρήστη;</string>
|
||||||
<string name="ConversationFragment_save_to_sd_card">Να αποθηκευτεί στη μνήμη;</string>
|
<string name="ConversationFragment_save_to_sd_card">Να αποθηκευτεί στη μνήμη;</string>
|
||||||
<plurals name="ConversationFragment_saving_n_media_to_storage_warning">
|
<plurals name="ConversationFragment_saving_n_media_to_storage_warning">
|
||||||
<item quantity="one">Αποθηκεύοντας αυτό το πολυμέσο στην μνήμη θα επιτρέψει σε άλλες εφαρμογές στην συσκευή σου να έχουν πρόσβαση σε αυτό. \n\nΣυνέχεια;</item>
|
<item quantity="one">Αποθηκεύοντας αυτό το πολυμέσο στην μνήμη θα επιτρέψει σε άλλες εφαρμογές στην συσκευή σου να έχουν πρόσβαση σε αυτό. \n\nΣυνέχεια;</item>
|
||||||
@ -122,8 +126,8 @@
|
|||||||
<string name="ConversationFragment_sms">SMS</string>
|
<string name="ConversationFragment_sms">SMS</string>
|
||||||
<string name="ConversationFragment_deleting">Γίνεται διαγραφή</string>
|
<string name="ConversationFragment_deleting">Γίνεται διαγραφή</string>
|
||||||
<string name="ConversationFragment_deleting_messages">Διαγραφή μηνυμάτων...</string>
|
<string name="ConversationFragment_deleting_messages">Διαγραφή μηνυμάτων...</string>
|
||||||
<string name="ConversationFragment_banning">Banning</string>
|
<string name="ConversationFragment_banning">Αποκλεισμός</string>
|
||||||
<string name="ConversationFragment_banning_user">Banning user…</string>
|
<string name="ConversationFragment_banning_user">Αποβολή Μέλους…</string>
|
||||||
<string name="ConversationFragment_quoted_message_not_found">Το αρχικό μήνυμα δε βρέθηκε</string>
|
<string name="ConversationFragment_quoted_message_not_found">Το αρχικό μήνυμα δε βρέθηκε</string>
|
||||||
<string name="ConversationFragment_quoted_message_no_longer_available">Το αρχικό μήνυμα δεν είναι πια διαθέσιμο</string>
|
<string name="ConversationFragment_quoted_message_no_longer_available">Το αρχικό μήνυμα δεν είναι πια διαθέσιμο</string>
|
||||||
<!-- ConversationListItem -->
|
<!-- ConversationListItem -->
|
||||||
@ -231,14 +235,14 @@
|
|||||||
<string name="ThreadRecord_s_is_on_signal">Ο/Η %s είναι στο Session!</string>
|
<string name="ThreadRecord_s_is_on_signal">Ο/Η %s είναι στο Session!</string>
|
||||||
<string name="ThreadRecord_disappearing_messages_disabled">Τα μηνύματα που εξαφανίζονται απενεργοποιήθηκαν</string>
|
<string name="ThreadRecord_disappearing_messages_disabled">Τα μηνύματα που εξαφανίζονται απενεργοποιήθηκαν</string>
|
||||||
<string name="ThreadRecord_disappearing_message_time_updated_to_s">Ο χρόνος εξαφάνισης των μηνυμάτων ρυθμίστηκε σε %s</string>
|
<string name="ThreadRecord_disappearing_message_time_updated_to_s">Ο χρόνος εξαφάνισης των μηνυμάτων ρυθμίστηκε σε %s</string>
|
||||||
<string name="ThreadRecord_s_took_a_screenshot">%s took a screenshot.</string>
|
<string name="ThreadRecord_s_took_a_screenshot">%s Στιγμιότυπο οθόνης.</string>
|
||||||
<string name="ThreadRecord_media_saved_by_s">Media saved by %s.</string>
|
<string name="ThreadRecord_media_saved_by_s">Μέσα αποθηκεύτηκαν από %s.</string>
|
||||||
<string name="ThreadRecord_safety_number_changed">Ο αριθμός ασφαλείας άλλαξε</string>
|
<string name="ThreadRecord_safety_number_changed">Ο αριθμός ασφαλείας άλλαξε</string>
|
||||||
<string name="ThreadRecord_your_safety_number_with_s_has_changed">Ο αριθμός ασφαλείας με τον/την %s έχει αλλάξει.</string>
|
<string name="ThreadRecord_your_safety_number_with_s_has_changed">Ο αριθμός ασφαλείας με τον/την %s έχει αλλάξει.</string>
|
||||||
<string name="ThreadRecord_you_marked_verified">Σημειώσατε ως επιβεβαιωμένο</string>
|
<string name="ThreadRecord_you_marked_verified">Σημειώσατε ως επιβεβαιωμένο</string>
|
||||||
<string name="ThreadRecord_you_marked_unverified">Σημειώσατε ως μη επιβεβαιωμένο</string>
|
<string name="ThreadRecord_you_marked_unverified">Σημειώσατε ως μη επιβεβαιωμένο</string>
|
||||||
<string name="ThreadRecord_empty_message">This conversation is empty</string>
|
<string name="ThreadRecord_empty_message">Αυτή η συνομιλία είναι κενή</string>
|
||||||
<string name="ThreadRecord_open_group_invitation">Open group invitation</string>
|
<string name="ThreadRecord_open_group_invitation">Πρόσκληση ανοιχτής ομάδας</string>
|
||||||
<!-- UpdateApkReadyListener -->
|
<!-- UpdateApkReadyListener -->
|
||||||
<string name="UpdateApkReadyListener_Signal_update">Αναβάθμιση Session</string>
|
<string name="UpdateApkReadyListener_Signal_update">Αναβάθμιση Session</string>
|
||||||
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Μια νέα έκδοση του Session είναι διαθέσιμη, πατήστε για αναβάθμιση</string>
|
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Μια νέα έκδοση του Session είναι διαθέσιμη, πατήστε για αναβάθμιση</string>
|
||||||
@ -274,7 +278,7 @@
|
|||||||
<string name="MessageNotifier_reply">Απάντηση</string>
|
<string name="MessageNotifier_reply">Απάντηση</string>
|
||||||
<string name="MessageNotifier_pending_signal_messages">Μηνύματα Session σε αναμονή</string>
|
<string name="MessageNotifier_pending_signal_messages">Μηνύματα Session σε αναμονή</string>
|
||||||
<string name="MessageNotifier_you_have_pending_signal_messages">Έχετε μηνύματα Session σε αναμονή, πατήστε για να τα ανοίξετε και να τα λάβετε</string>
|
<string name="MessageNotifier_you_have_pending_signal_messages">Έχετε μηνύματα Session σε αναμονή, πατήστε για να τα ανοίξετε και να τα λάβετε</string>
|
||||||
<string name="MessageNotifier_contact_message">%1$s %2$s</string>
|
<string name="MessageNotifier_contact_message">%1$s, %2$s</string>
|
||||||
<string name="MessageNotifier_unknown_contact_message">Επαφή</string>
|
<string name="MessageNotifier_unknown_contact_message">Επαφή</string>
|
||||||
<!-- Notification Channels -->
|
<!-- Notification Channels -->
|
||||||
<string name="NotificationChannel_messages">Προκαθορισμένο</string>
|
<string name="NotificationChannel_messages">Προκαθορισμένο</string>
|
||||||
@ -297,7 +301,7 @@
|
|||||||
<!-- ShortcutLauncherActivity -->
|
<!-- ShortcutLauncherActivity -->
|
||||||
<string name="ShortcutLauncherActivity_invalid_shortcut">Μη έγκυρη συντόμευση</string>
|
<string name="ShortcutLauncherActivity_invalid_shortcut">Μη έγκυρη συντόμευση</string>
|
||||||
<!-- SingleRecipientNotificationBuilder -->
|
<!-- SingleRecipientNotificationBuilder -->
|
||||||
<string name="SingleRecipientNotificationBuilder_signal">Session</string>
|
<string name="SingleRecipientNotificationBuilder_signal">Συνεδρία</string>
|
||||||
<string name="SingleRecipientNotificationBuilder_new_message">Νέο μήνυμα</string>
|
<string name="SingleRecipientNotificationBuilder_new_message">Νέο μήνυμα</string>
|
||||||
<!-- TransferControlView -->
|
<!-- TransferControlView -->
|
||||||
<plurals name="TransferControlView_n_items">
|
<plurals name="TransferControlView_n_items">
|
||||||
@ -351,8 +355,11 @@
|
|||||||
<string name="audio_view__pause_accessibility_description">Παύση</string>
|
<string name="audio_view__pause_accessibility_description">Παύση</string>
|
||||||
<string name="audio_view__download_accessibility_description">Λήψη</string>
|
<string name="audio_view__download_accessibility_description">Λήψη</string>
|
||||||
<!-- open_group_invitation_view -->
|
<!-- open_group_invitation_view -->
|
||||||
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
<string name="open_group_invitation_view__join_accessibility_description">Εγγραφείτε</string>
|
||||||
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
<string name="open_group_invitation_view__open_group_invitation">Πρόσκληση ανοιχτής ομάδας</string>
|
||||||
|
<string name="open_group_guidelines_pinned_message">Καρφιτσωμένο Μήνυμα</string>
|
||||||
|
<string name="open_group_guidelines_community_guidelines">Οδηγίες Κοινότητας</string>
|
||||||
|
<string name="open_group_guidelines_read">Διαβάστηκε</string>
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Ήχος</string>
|
<string name="QuoteView_audio">Ήχος</string>
|
||||||
<string name="QuoteView_video">Βίντεο</string>
|
<string name="QuoteView_video">Βίντεο</string>
|
||||||
@ -482,7 +489,7 @@
|
|||||||
<string name="conversation_context__menu_message_details">Στοιχεία μηνύματος</string>
|
<string name="conversation_context__menu_message_details">Στοιχεία μηνύματος</string>
|
||||||
<string name="conversation_context__menu_copy_text">Αντιγραφή κειμένου</string>
|
<string name="conversation_context__menu_copy_text">Αντιγραφή κειμένου</string>
|
||||||
<string name="conversation_context__menu_delete_message">Διαγραφή μηνύματος</string>
|
<string name="conversation_context__menu_delete_message">Διαγραφή μηνύματος</string>
|
||||||
<string name="conversation_context__menu_ban_user">Ban user</string>
|
<string name="conversation_context__menu_ban_user">Αποκλεισμός χρήστη</string>
|
||||||
<string name="conversation_context__menu_resend_message">Αποστολή ξανά</string>
|
<string name="conversation_context__menu_resend_message">Αποστολή ξανά</string>
|
||||||
<string name="conversation_context__menu_reply_to_message">Απαντήστε στο μήνυμα</string>
|
<string name="conversation_context__menu_reply_to_message">Απαντήστε στο μήνυμα</string>
|
||||||
<!-- conversation_context_image -->
|
<!-- conversation_context_image -->
|
||||||
@ -542,138 +549,153 @@
|
|||||||
<string name="preferences_app_protection__screen_lock_inactivity_timeout">Χρονικό όριο αδράνειας κλειδώματος οθόνης</string>
|
<string name="preferences_app_protection__screen_lock_inactivity_timeout">Χρονικό όριο αδράνειας κλειδώματος οθόνης</string>
|
||||||
<string name="AppProtectionPreferenceFragment_none">Κανένα</string>
|
<string name="AppProtectionPreferenceFragment_none">Κανένα</string>
|
||||||
<!-- Conversation activity -->
|
<!-- Conversation activity -->
|
||||||
<string name="activity_conversation_copy_public_key_button_title">Copy public key</string>
|
<string name="activity_conversation_copy_public_key_button_title">Αντιγραφή δημόσιου κλειδιού</string>
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
<string name="continue_2">Continue</string>
|
<string name="continue_2">Συνέχεια</string>
|
||||||
<string name="copy">Copy</string>
|
<string name="copy">Αντιγραφή</string>
|
||||||
<string name="invalid_url">Invalid URL</string>
|
<string name="invalid_url">Μη έγκυρη διεύθυνση URL</string>
|
||||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
<string name="copied_to_clipboard">Αντιγράφηκε στο πρόχειρο</string>
|
||||||
<string name="next">Next</string>
|
<string name="next">Επόμενο</string>
|
||||||
<string name="share">Share</string>
|
<string name="share">Διαμοιρασμός</string>
|
||||||
<string name="invalid_session_id">Invalid Session ID</string>
|
<string name="invalid_session_id">Μη έγκυρη Session ταυτότητα</string>
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Ακύρωση</string>
|
||||||
<string name="your_session_id">Your Session ID</string>
|
<string name="your_session_id">Η ταυτότητά σας</string>
|
||||||
<string name="activity_landing_title_2">Your Session begins here...</string>
|
<string name="activity_landing_title_2">Η συνομιλία σας ξεκινά εδώ...</string>
|
||||||
<string name="activity_landing_register_button_title">Create Session ID</string>
|
<string name="activity_landing_register_button_title">Δημιουργία Session ταυτότητας</string>
|
||||||
<string name="activity_landing_restore_button_title">Continue Your Session</string>
|
<string name="activity_landing_restore_button_title">Συνέχεια συνομιλίας</string>
|
||||||
<string name="view_fake_chat_bubble_1">What\'s Session?</string>
|
<string name="view_fake_chat_bubble_1">Τι είναι το Session;</string>
|
||||||
<string name="view_fake_chat_bubble_2">It\'s a decentralized, encrypted messaging app</string>
|
<string name="view_fake_chat_bubble_2">Είναι μια αποκεντρωμένη, κρυπτογραφημένη εφαρμογή μηνυμάτων</string>
|
||||||
<string name="view_fake_chat_bubble_3">So it doesn\'t collect my personal information or my conversation metadata? How does it work?</string>
|
<string name="view_fake_chat_bubble_3">Δηλαδή δεν συλλέγει τα προσωπικά μου στοιχεία ή τα μεταδεδομένα των συνομιλιών μου; Πώς λειτουργεί;</string>
|
||||||
<string name="view_fake_chat_bubble_4">Using a combination of advanced anonymous routing and end-to-end encryption technologies.</string>
|
<string name="view_fake_chat_bubble_4">Χρησιμοποιώντας ένα συνδυασμό προηγμένων ανώνυμων τεχνολογιών δρομολόγησης και τεχνολογίας κρυπτογράφησης από άκρο σε άκρο.</string>
|
||||||
<string name="view_fake_chat_bubble_5">Friends don\'t let friends use compromised messengers. You\'re welcome.</string>
|
<string name="view_fake_chat_bubble_5">Οι φίλοι δεν αφήνουν τους φίλους να χρησιμοποιούν ευάλωτες εφαρμογές μηνυμάτων. Είστε ευπρόσδεκτοι.</string>
|
||||||
<string name="activity_register_title">Say hello to your Session ID</string>
|
<string name="activity_register_title">Πείτε γεια στη Session ταυτότητά σας</string>
|
||||||
<string name="activity_register_explanation">Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.</string>
|
<string name="activity_register_explanation">Η Session ταυτότητά σας είναι η μοναδική διεύθυνση που μπορούν να χρησιμοποιήσουν τα άτομα για να επικοινωνήσουν μαζί σας στο Session. Χωρίς σύνδεση με την πραγματική σας ταυτότητα, η Session ταυτότητά σας είναι εντελώς ανώνυμη και ιδιωτική.</string>
|
||||||
<string name="activity_restore_title">Restore your account</string>
|
<string name="activity_restore_title">Επαναφορά του λογαριασμού σας</string>
|
||||||
<string name="activity_restore_explanation">Enter the recovery phrase that was given to you when you signed up to restore your account.</string>
|
<string name="activity_restore_explanation">Εισάγετε τη φράση ανάκτησης που σας δόθηκε κατά την εγγραφή σας για να επαναφέρετε το λογαριασμό σας.</string>
|
||||||
<string name="activity_restore_seed_edit_text_hint">Enter your recovery phrase</string>
|
<string name="activity_restore_seed_edit_text_hint">Εισάγετε τη φράση ανάκτησης σας</string>
|
||||||
<string name="activity_display_name_title_2">Pick your display name</string>
|
<string name="activity_display_name_title_2">Επιλέξτε το εμφανιζόμενο όνομα σας</string>
|
||||||
<string name="activity_display_name_explanation">This will be your name when you use Session. It can be your real name, an alias, or anything else you like.</string>
|
<string name="activity_display_name_explanation">Αυτό θα είναι το όνομά σας όταν χρησιμοποιείτε το Session. Μπορεί να είναι το πραγματικό σας όνομα, ένα ψευδώνυμο ή οτιδήποτε άλλο θέλετε.</string>
|
||||||
<string name="activity_display_name_edit_text_hint">Enter a display name</string>
|
<string name="activity_display_name_edit_text_hint">Εισάγετε όνομα εμφάνισης</string>
|
||||||
<string name="activity_display_name_display_name_missing_error">Please pick a display name</string>
|
<string name="activity_display_name_display_name_missing_error">Παρακαλώ επιλέξτε ένα εμφανιζόμενο όνομα</string>
|
||||||
<string name="activity_display_name_display_name_too_long_error">Please pick a shorter display name</string>
|
<string name="activity_display_name_display_name_too_long_error">Παρακαλώ επιλέξτε ένα μικρότερο όνομα εμφάνισης</string>
|
||||||
<string name="activity_pn_mode_recommended_option_tag">Recommended</string>
|
<string name="activity_pn_mode_recommended_option_tag">Προτεινόμενο</string>
|
||||||
<string name="activity_pn_mode_no_option_picked_dialog_title">Please Pick an Option</string>
|
<string name="activity_pn_mode_no_option_picked_dialog_title">Παρακαλούμε κάντε μια επιλογή</string>
|
||||||
<string name="activity_home_empty_state_message">You don\'t have any contacts yet</string>
|
<string name="activity_home_empty_state_message">Δεν υπάρχουν επαφές</string>
|
||||||
<string name="activity_home_empty_state_button_title">Start a Session</string>
|
<string name="activity_home_empty_state_button_title">Ξεκινήστε μια συνομιλία</string>
|
||||||
<string name="activity_home_leave_group_dialog_message">Are you sure you want to leave this group?</string>
|
<string name="activity_home_leave_group_dialog_message">Είστε βέβαιοι ότι θέλετε να φύγετε από αυτή την ομάδα;</string>
|
||||||
<string name="activity_home_leaving_group_failed_message">"Couldn't leave group"</string>
|
<string name="activity_home_leaving_group_failed_message">"Αδυναμία αποχώρησης από την ομάδα"</string>
|
||||||
<string name="activity_home_delete_conversation_dialog_message">Are you sure you want to delete this conversation?</string>
|
<string name="activity_home_delete_conversation_dialog_message">Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτήν την συνομιλία;</string>
|
||||||
<string name="activity_home_conversation_deleted_message">Conversation deleted</string>
|
<string name="activity_home_conversation_deleted_message">Η συνομιλία διαγράφηκε</string>
|
||||||
<string name="activity_seed_title">Your Recovery Phrase</string>
|
<string name="activity_seed_title">Φράση ανάκτησης</string>
|
||||||
<string name="activity_seed_title_2">Meet your recovery phrase</string>
|
<string name="activity_seed_title_2">Γνωρίστε τη φράση ανάκτησής σας</string>
|
||||||
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\'t give it to anyone.</string>
|
<string name="activity_seed_explanation">Η φράση ανάκτησης είναι το κύριο κλειδί στο Session ID σας - μπορείτε να τη χρησιμοποιήσετε για να επαναφέρετε το Session ID σας εάν χάσετε πρόσβαση στη συσκευή σας. Αποθηκεύστε τη φράση ανάκτησης σε ασφαλές μέρος, και μην τη δώσετε σε κανέναν.</string>
|
||||||
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
|
<string name="activity_seed_reveal_button_title">Πατήστε για εμφάνιση</string>
|
||||||
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
|
<string name="view_seed_reminder_title">Σχεδόν τελειώσατε! 80%</string>
|
||||||
<string name="view_seed_reminder_subtitle_2">Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.</string>
|
<string name="view_seed_reminder_subtitle_1">Ασφαλίστε το λογαριασμό σας αποθηκεύοντας τη φράση ανάκτησής σας</string>
|
||||||
<string name="view_seed_reminder_subtitle_3">Make sure to store your recovery phrase in a safe place</string>
|
<string name="view_seed_reminder_subtitle_2">Πατήστε παρατεταμένα τις λέξεις που τροποποιήθηκαν για να αποκαλύψετε τη φράση ανάκτησης και μετά αποθηκεύστε την με ασφάλεια για να εξασφαλίσετε το αναγνωριστικό σας.</string>
|
||||||
<string name="activity_path_title">Path</string>
|
<string name="view_seed_reminder_subtitle_3">Φροντίστε να αποθηκεύσετε τη φράση ανάκτησής σας σε ασφαλές μέρος</string>
|
||||||
<string name="activity_path_explanation">Session hides your IP by bouncing your messages through several Service Nodes in Session\'s decentralized network. These are the countries your connection is currently being bounced through:</string>
|
<string name="activity_path_title">Διαδρομή</string>
|
||||||
<string name="activity_path_device_row_title">You</string>
|
<string name="activity_path_explanation">Το Session αποκρύπτει την IP σας, δρομολογώντας τα μηνύματά σας μέσω αρκετών Κόμβων υπηρεσιών στο αποκεντρωμένο Session δίκτυο. Αυτές είναι οι χώρες που δρομολογείται η σύνδεσή σας αυτή τη στιγμή:</string>
|
||||||
<string name="activity_path_guard_node_row_title">Entry Node</string>
|
<string name="activity_path_device_row_title">Εσείς</string>
|
||||||
<string name="activity_path_service_node_row_title">Service Node</string>
|
<string name="activity_path_guard_node_row_title">Κόμβος Εισόδου</string>
|
||||||
<string name="activity_path_destination_row_title">Destination</string>
|
<string name="activity_path_service_node_row_title">Κόμβος Υπηρεσίας</string>
|
||||||
<string name="activity_path_learn_more_button_title">Learn More</string>
|
<string name="activity_path_destination_row_title">Προορισμός</string>
|
||||||
<string name="activity_create_private_chat_title">New Session</string>
|
<string name="activity_path_learn_more_button_title">Μάθετε περισσότερα</string>
|
||||||
<string name="activity_create_private_chat_enter_session_id_tab_title">Enter Session ID</string>
|
<string name="activity_create_private_chat_title">Νέα συνομιλία</string>
|
||||||
<string name="activity_create_private_chat_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_create_private_chat_enter_session_id_tab_title">Εισαγωγή Session Ταυτότητας</string>
|
||||||
<string name="activity_create_private_chat_scan_qr_code_explanation">Scan a user\'s QR code to start a session. QR codes can be found by tapping the QR code icon in account settings.</string>
|
<string name="activity_create_private_chat_scan_qr_code_tab_title">Σαρώστε τον κωδικό QR</string>
|
||||||
<string name="fragment_enter_public_key_edit_text_hint">Enter Session ID of recipient</string>
|
<string name="activity_create_private_chat_scan_qr_code_explanation">Σαρώστε τον κωδικό QR ενός χρήστη για να ξεκινήσετε μια συνομιλία. Οι κωδικοί QR μπορούν να βρεθούν πατώντας το εικονίδιο QR κώδικα στις ρυθμίσεις λογαριασμού.</string>
|
||||||
<string name="fragment_enter_public_key_explanation">Users can share their Session ID by going into their account settings and tapping \"Share Session ID\", or by sharing their QR code.</string>
|
<string name="fragment_enter_public_key_edit_text_hint">Εισάγετε τη ταυτότητα του παραλήπτη</string>
|
||||||
<string name="fragment_scan_qr_code_camera_access_explanation">Session needs camera access to scan QR codes</string>
|
<string name="fragment_enter_public_key_explanation">Οι χρήστες μπορούν να μοιραστούν τη ταυτότητα τους πηγαίνοντας στις ρυθμίσεις του λογαριασμού τους και πατώντας το \"Διαμοιρασμό Session ταυτότητας\" ή κοινοποιώντας τον κωδικό QR.</string>
|
||||||
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Grant Camera Access</string>
|
<string name="fragment_scan_qr_code_camera_access_explanation">Το Session χρειάζεται πρόσβαση στην κάμερα για σάρωση κωδικών QR</string>
|
||||||
<string name="activity_create_closed_group_title">New Closed Group</string>
|
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Χορήγηση Πρόσβασης Κάμερας</string>
|
||||||
<string name="activity_create_closed_group_edit_text_hint">Enter a group name</string>
|
<string name="activity_create_closed_group_title">Νέα Κλειστή Ομάδα</string>
|
||||||
<string name="activity_create_closed_group_empty_state_message">You don\'t have any contacts yet</string>
|
<string name="activity_create_closed_group_edit_text_hint">Εισαγωγή ονόματος ομάδας</string>
|
||||||
<string name="activity_create_closed_group_empty_state_button_title">Start a Session</string>
|
<string name="activity_create_closed_group_empty_state_message">Δεν υπάρχουν επαφές</string>
|
||||||
<string name="activity_create_closed_group_group_name_missing_error">Please enter a group name</string>
|
<string name="activity_create_closed_group_empty_state_button_title">Ξεκινήστε μια συνομιλία</string>
|
||||||
<string name="activity_create_closed_group_group_name_too_long_error">Please enter a shorter group name</string>
|
<string name="activity_create_closed_group_group_name_missing_error">Παρακαλώ εισάγετε όνομα ομάδας</string>
|
||||||
<string name="activity_create_closed_group_not_enough_group_members_error">Please pick at least 1 group member</string>
|
<string name="activity_create_closed_group_group_name_too_long_error">Παρακαλούμε εισάγετε ένα μικρότερο όνομα ομάδας</string>
|
||||||
<string name="activity_create_closed_group_too_many_group_members_error">A closed group cannot have more than 100 members</string>
|
<string name="activity_create_closed_group_not_enough_group_members_error">Παρακαλώ επιλέξτε τουλάχιστον 1 μέλος ομάδας</string>
|
||||||
<string name="activity_join_public_chat_title">Join Open Group</string>
|
<string name="activity_create_closed_group_too_many_group_members_error">Μια κλειστή ομάδα δεν μπορεί να έχει περισσότερα από 100 μέλη</string>
|
||||||
<string name="activity_join_public_chat_error">Couldn\'t join group</string>
|
<string name="activity_join_public_chat_title">Συμμετοχή Σε Ανοιχτή Ομάδα</string>
|
||||||
<string name="activity_join_public_chat_enter_group_url_tab_title">Open Group URL</string>
|
<string name="activity_join_public_chat_error">Αδυναμία συμμετοχής στην ομάδα</string>
|
||||||
<string name="activity_join_public_chat_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_join_public_chat_enter_group_url_tab_title">Διεύθυνση Ανοιχτής Ομάδας</string>
|
||||||
<string name="activity_join_public_chat_scan_qr_code_explanation">Scan the QR code of the open group you\'d like to join</string>
|
<string name="activity_join_public_chat_scan_qr_code_tab_title">Σάρωση QR κωδικού</string>
|
||||||
<string name="fragment_enter_chat_url_edit_text_hint">Enter an open group URL</string>
|
<string name="activity_join_public_chat_scan_qr_code_explanation">Σαρώστε τον κωδικό QR της ανοικτής ομάδας που θα θέλατε να συμμετάσχετε</string>
|
||||||
<string name="activity_settings_title">Settings</string>
|
<string name="fragment_enter_chat_url_edit_text_hint">Εισάγετε μια διεύθυνση ανοικτής ομάδας</string>
|
||||||
<string name="activity_settings_display_name_edit_text_hint">Enter a display name</string>
|
<string name="activity_settings_title">Ρυθμίσεις</string>
|
||||||
<string name="activity_settings_display_name_missing_error">Please pick a display name</string>
|
<string name="activity_settings_display_name_edit_text_hint">Εισάγετε ένα όνομα</string>
|
||||||
<string name="activity_settings_display_name_too_long_error">Please pick a shorter display name</string>
|
<string name="activity_settings_display_name_missing_error">Παρακαλώ διαλέξτε ένα όνομα εμφάνισης</string>
|
||||||
<string name="activity_settings_privacy_button_title">Privacy</string>
|
<string name="activity_settings_display_name_too_long_error">Παρακαλώ επιλέξτε ένα μικρότερο όνομα εμφάνισης</string>
|
||||||
<string name="activity_settings_notifications_button_title">Notifications</string>
|
<string name="activity_settings_privacy_button_title">Ιδιωτικότητα</string>
|
||||||
<string name="activity_settings_chats_button_title">Chats</string>
|
<string name="activity_settings_notifications_button_title">Ειδοποιήσεις</string>
|
||||||
<string name="activity_settings_devices_button_title">Devices</string>
|
<string name="activity_settings_chats_button_title">Συνομιλίες</string>
|
||||||
<string name="activity_settings_invite_button_title">Invite</string>
|
<string name="activity_settings_devices_button_title">Συσκευές</string>
|
||||||
<string name="activity_settings_recovery_phrase_button_title">Recovery Phrase</string>
|
<string name="activity_settings_invite_button_title">Πρόσκληση</string>
|
||||||
<string name="activity_settings_clear_all_data_button_title">Clear Data</string>
|
<string name="activity_settings_recovery_phrase_button_title">Φράση Ανάκτησης</string>
|
||||||
<string name="activity_notification_settings_title">Notifications</string>
|
<string name="activity_settings_clear_all_data_button_title">Εκκαθάριση Δεδομένων</string>
|
||||||
<string name="activity_notification_settings_style_section_title">Notification Style</string>
|
<string name="activity_settings_help_translate_session">Βοηθήστε μας να μεταφράσουμε τη συνεδρία</string>
|
||||||
<string name="activity_notification_settings_content_section_title">Notification Content</string>
|
<string name="activity_notification_settings_title">Ειδοποιήσεις</string>
|
||||||
<string name="activity_privacy_settings_title">Privacy</string>
|
<string name="activity_notification_settings_style_section_title">Στυλ ειδοποιήσεων</string>
|
||||||
<string name="activity_chat_settings_title">Chats</string>
|
<string name="activity_notification_settings_content_section_title">Περιεχόμενο Ειδοποιήσεων</string>
|
||||||
<string name="preferences_notifications_strategy_category_title">Notification Strategy</string>
|
<string name="activity_privacy_settings_title">Απόρρητο</string>
|
||||||
<string name="fragment_device_list_bottom_sheet_change_name_button_title">Change name</string>
|
<string name="activity_chat_settings_title">Συνομιλίες</string>
|
||||||
<string name="fragment_device_list_bottom_sheet_unlink_device_button_title">Unlink device</string>
|
<string name="preferences_notifications_strategy_category_title">Περιεχόμενο Ειδοποιήσεων</string>
|
||||||
<string name="dialog_seed_title">Your Recovery Phrase</string>
|
<string name="fragment_device_list_bottom_sheet_change_name_button_title">Αλλαγή ονόματος</string>
|
||||||
<string name="dialog_seed_explanation">This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device.</string>
|
<string name="fragment_device_list_bottom_sheet_unlink_device_button_title">Αποσύνδεση Συσκευής</string>
|
||||||
<string name="dialog_clear_all_data_title">Clear All Data</string>
|
<string name="dialog_seed_title">Η φράση ανάκτησής σας</string>
|
||||||
<string name="dialog_clear_all_data_explanation">This will permanently delete your messages, sessions, and contacts.</string>
|
<string name="dialog_seed_explanation">Αυτή είναι η φράση ανάκτησης σας. Με αυτή, μπορείτε να επαναφέρετε ή να μεταφέρετε τη Session ταυτότητά σας σε μια νέα συσκευή.</string>
|
||||||
<string name="activity_qr_code_title">QR Code</string>
|
<string name="dialog_clear_all_data_title">Εκκαθάριση όλων των δεδομένων</string>
|
||||||
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>
|
<string name="dialog_clear_all_data_explanation">Αυτό θα διαγράψει μόνιμα τα μηνύματα, τις συνομιλίες και τις επαφές σας.</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_tab_title">Scan QR Code</string>
|
<string name="activity_qr_code_title">QR κωδικός</string>
|
||||||
<string name="activity_qr_code_view_scan_qr_code_explanation">Scan someone\'s QR code to start a conversation with them</string>
|
<string name="activity_qr_code_view_my_qr_code_tab_title">Προβολή Του Qr Κώδικά Μου</string>
|
||||||
<string name="fragment_view_my_qr_code_explanation">This is your QR code. Other users can scan it to start a session with you.</string>
|
<string name="activity_qr_code_view_scan_qr_code_tab_title">Σαρώστε τον κωδικό QR</string>
|
||||||
<string name="fragment_view_my_qr_code_share_title">Share QR Code</string>
|
<string name="activity_qr_code_view_scan_qr_code_explanation">Σαρώστε τον κωδικό QR κάποιου για να ξεκινήσετε μια συνομιλία μαζί του</string>
|
||||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
<string name="fragment_view_my_qr_code_title">Σάρωσέ Με</string>
|
||||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
<string name="fragment_view_my_qr_code_explanation">Αυτός είναι ο προσωπικός σας κωδικός QR. Άλλοι χρήστες μπορούν να τον σαρώσουν για να ξεκινήσουν μια συνομιλία μαζί σας.</string>
|
||||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
<string name="fragment_view_my_qr_code_share_title">Κοινοποίηση κωδικού QR</string>
|
||||||
|
<string name="fragment_contact_selection_contacts_title">Επαφές</string>
|
||||||
|
<string name="fragment_contact_selection_closed_groups_title">Κλειστές Ομάδες</string>
|
||||||
|
<string name="fragment_contact_selection_open_groups_title">Ανοικτές Ομάδες</string>
|
||||||
|
<string name="fragment_contact_selection_empty_contacts">Δεν έχετε επαφές ακόμη</string>
|
||||||
<!-- Next round of translation -->
|
<!-- Next round of translation -->
|
||||||
<string name="menu_apply_button">Apply</string>
|
<string name="menu_apply_button">Εφαρμογή</string>
|
||||||
<string name="menu_done_button">Done</string>
|
<string name="menu_done_button">Τέλος</string>
|
||||||
<string name="activity_edit_closed_group_title">Edit Group</string>
|
<string name="activity_edit_closed_group_title">Επεξεργασία Ομάδας</string>
|
||||||
<string name="activity_edit_closed_group_edit_text_hint">Enter a new group name</string>
|
<string name="activity_edit_closed_group_edit_text_hint">Εισαγωγή νέου ονόματος ομάδας</string>
|
||||||
<string name="activity_edit_closed_group_edit_members">Members</string>
|
<string name="activity_edit_closed_group_edit_members">Μέλη</string>
|
||||||
<string name="activity_edit_closed_group_add_members">Add members</string>
|
<string name="activity_edit_closed_group_add_members">Προσθήκη μελών</string>
|
||||||
<string name="activity_edit_closed_group_group_name_missing_error">Group name can\'t be empty</string>
|
<string name="activity_edit_closed_group_group_name_missing_error">Το όνομα ομάδας δεν μπορεί να είναι κενό</string>
|
||||||
<string name="activity_edit_closed_group_group_name_too_long_error">Please enter a shorter group name</string>
|
<string name="activity_edit_closed_group_group_name_too_long_error">Παρακαλούμε εισάγετε ένα μικρότερο όνομα ομάδας</string>
|
||||||
<string name="activity_edit_closed_group_not_enough_group_members_error">Groups must have at least 1 group member</string>
|
<string name="activity_edit_closed_group_not_enough_group_members_error">Οι ομάδες πρέπει να έχουν τουλάχιστον 1 μέλος ομάδας</string>
|
||||||
<string name="fragment_edit_group_bottom_sheet_remove">Remove user from group</string>
|
<string name="fragment_edit_group_bottom_sheet_remove">Αφαίρεση Χρήστη Από την Ομάδα</string>
|
||||||
<string name="activity_select_contacts_title">Select Contacts</string>
|
<string name="activity_select_contacts_title">Επιλογή Επαφών</string>
|
||||||
<string name="view_reset_secure_session_done_message">Secure session reset done</string>
|
<string name="view_reset_secure_session_done_message">Η ασφαλής επαναφορά ολοκληρώθηκε</string>
|
||||||
<string name="dialog_ui_mode_title">Theme</string>
|
<string name="dialog_ui_mode_title">Θέμα</string>
|
||||||
<string name="dialog_ui_mode_option_day">Day</string>
|
<string name="dialog_ui_mode_option_day">Ημέρα</string>
|
||||||
<string name="dialog_ui_mode_option_night">Night</string>
|
<string name="dialog_ui_mode_option_night">Νύχτα</string>
|
||||||
<string name="dialog_ui_mode_option_system_default">System default</string>
|
<string name="dialog_ui_mode_option_system_default">Προεπιλογή συστήματος</string>
|
||||||
<string name="activity_conversation_menu_copy_session_id">Copy Session ID</string>
|
<string name="activity_conversation_menu_copy_session_id">Αντιγραφή Ταυτότητας</string>
|
||||||
<string name="attachment">Attachment</string>
|
<string name="attachment">Συνημμένο</string>
|
||||||
<string name="attachment_type_voice_message">Voice Message</string>
|
<string name="attachment_type_voice_message">Ηχητικό μήνυμα</string>
|
||||||
<string name="details">Details</string>
|
<string name="details">Λεπτομέρειες</string>
|
||||||
<string name="dialog_backup_activation_failed">Failed to activate backups. Please try again or contact support.</string>
|
<string name="dialog_backup_activation_failed">Αποτυχία ενεργοποίησης αντιγράφων ασφαλείας. Παρακαλώ δοκιμάστε ξανά ή επικοινωνήστε με την υποστήριξη.</string>
|
||||||
<string name="activity_backup_restore_title">Restore backup</string>
|
<string name="activity_backup_restore_title">Επαναφορά αντίγραφου ασφαλείας</string>
|
||||||
<string name="activity_backup_restore_select_file">Select a file</string>
|
<string name="activity_backup_restore_select_file">Επιλέξτε ένα αρχείο</string>
|
||||||
<string name="activity_backup_restore_explanation_1">Select a backup file and enter the passphrase it was created with.</string>
|
<string name="activity_backup_restore_explanation_1">Επιλέξτε ένα αντίγραφο ασφαλείας και εισάγετε τη φράση πρόσβασης με την οποία δημιουργήθηκε.</string>
|
||||||
<string name="activity_backup_restore_passphrase">30-digit passphrase</string>
|
<string name="activity_backup_restore_passphrase">φράση 30-ψηφίων</string>
|
||||||
<!-- LinkDeviceActivity -->
|
<string name="activity_link_device_skip_prompt">Αυτό παίρνει λίγο χρόνο, θα θέλατε να παραλείψετε;</string>
|
||||||
<string name="activity_link_device_skip_prompt">This is taking a while, would you like to skip?</string>
|
<string name="activity_link_device_link_device">Σύνδεση Συσκευής</string>
|
||||||
<string name="activity_join_public_chat_join_rooms">Or join one of these…</string>
|
<string name="activity_join_public_chat_join_rooms">Ή συνδεθείτε σε ένα από αυτά…</string>
|
||||||
|
<string name="activity_pn_mode_message_notifications">Ειδοποίησεις μηνυμάτων</string>
|
||||||
|
<string name="activity_pn_mode_explanation">Υπάρχουν δύο τρόποι με τους οποίους το Session μπορεί να σας ειδοποιήσει για νέα μηνύματα.</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode">Γρήγορη Επιλογή</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode">Αργή Επιλογή</string>
|
||||||
|
<string name="activity_pn_mode_fast_mode_explanation">Θα ειδοποιηθείτε για νέα μηνύματα αξιόπιστα και άμεσα χρησιμοποιώντας τους διακομιστές ειδοποιήσεων της Google.</string>
|
||||||
|
<string name="activity_pn_mode_slow_mode_explanation">Το Session θα ελέγχει κατά καιρούς για νέα μηνύματα στο παρασκήνιο.</string>
|
||||||
|
<string name="fragment_recovery_phrase_title">Φράση Ανάκτησης</string>
|
||||||
|
<string name="activity_prompt_passphrase_session_locked">Το Session είναι κλειδωμένο</string>
|
||||||
|
<string name="activity_prompt_passphrase_tap_to_unlock">Πατήστε για ξεκλείδωμα</string>
|
||||||
|
<string name="fragment_user_details_bottom_sheet_edit_text_hint">Enter a nickname</string>
|
||||||
|
<string name="invalid_public_key">Invalid public key</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user